This source file includes following definitions.
- it_char_has_category
- char_can_wrap_before
- char_can_wrap_after
- fill_column_indicator_column
- redisplay_other_windows
- wset_redisplay
- fset_redisplay
- bset_redisplay
- bset_update_mode_line
- wset_update_mode_line
- ATTRIBUTE_FORMAT_PRINTF
- ATTRIBUTE_FORMAT_PRINTF
- window_text_bottom_y
- window_box_width
- window_box_height
- window_box_left_offset
- window_box_right_offset
- window_box_left
- window_box_right
- window_box
- window_box_edges
- line_bottom_y
- DEFUN
- default_line_pixel_height
- string_from_display_spec
- window_hscroll_limited
- reset_box_start_end_flags
- pos_visible_p
- check_char_and_length
- string_pos_nchars_ahead
- string_pos
- c_string_pos
- number_of_chars
- compute_string_pos
- estimate_mode_line_height
- pixel_to_glyph_coords
- x_y_to_hpos_vpos
- frame_to_window_pixel_xy
- get_glyph_string_clip_rects
- get_glyph_string_clip_rect
- get_phys_cursor_geometry
- remember_mouse_glyph
- adjust_window_ends
- hscrolling_current_line_p
- safe_eval_handler
- safe__call
- safe_call
- safe_call1
- safe__call1
- safe_eval
- safe__eval
- safe_call2
- CHECK_IT
- CHECK_WINDOW_END
- init_iterator
- get_narrowed_width
- get_narrowed_len
- get_medium_narrowing_begv
- get_medium_narrowing_zv
- get_nearby_bol_pos
- get_small_narrowing_begv
- get_large_narrowing_begv
- get_large_narrowing_zv
- unwind_narrowed_begv
- start_display
- in_ellipses_for_invisible_text_p
- init_from_display_pos
- init_to_row_start
- init_to_row_end
- handle_stop
- compute_stop_pos
- compute_display_string_pos
- compute_display_string_end
- handle_fontified_prop
- face_at_pos
- handle_face_prop
- underlying_face_id
- face_before_or_after_it_pos
- handle_invisible_prop
- setup_for_ellipsis
- find_display_property
- get_display_property
- display_min_width
- handle_display_prop
- handle_display_spec
- display_prop_end
- handle_single_display_spec
- display_prop_intangible_p
- single_display_spec_string_p
- display_prop_string_p
- string_buffer_position_lim
- string_buffer_position
- handle_composition_prop
- handle_overlay_change
- next_overlay_string
- compare_overlay_entries
- load_overlay_strings
- get_overlay_strings_1
- get_overlay_strings
- push_it
- iterate_out_of_display_property
- restore_face_box_flags
- pop_it
- back_to_previous_line_start
- strings_with_newlines
- forward_to_next_line_start
- back_to_previous_visible_line_start
- reseat_at_previous_visible_line_start
- reseat_at_next_visible_line_start
- reseat
- reseat_1
- reseat_to_string
- lookup_glyphless_char_display
- merge_escape_glyph_face
- merge_glyphless_glyph_face
- forget_escape_and_glyphless_faces
- get_next_display_element
- set_iterator_to_next
- next_element_from_display_vector
- get_visually_first_element
- next_element_from_string
- next_element_from_c_string
- next_element_from_ellipsis
- next_element_from_image
- next_element_from_xwidget
- next_element_from_stretch
- compute_stop_pos_backwards
- handle_stop_backwards
- next_element_from_buffer
- next_element_from_composition
- move_it_in_display_line_to
- move_it_in_display_line
- move_it_to
- move_it_vertically_backward
- move_it_vertically
- move_it_past_eol
- move_it_by_lines
- partial_line_height
- fast_move_it_horizontally
- in_display_vector_p
- window_text_pixel_size
- DEFUN
- format_nargs
- add_to_log
- vadd_to_log
- message_log_maybe_newline
- message_dolog
- message_log_check_duplicate
- message3
- message_to_stderr
- message3_nolog
- message1
- message1_nolog
- message_with_string
- ATTRIBUTE_FORMAT_PRINTF
- message
- update_echo_area
- ensure_echo_area_buffers
- with_echo_area_buffer
- with_echo_area_buffer_unwind_data
- unwind_with_echo_area_buffer
- setup_echo_area_for_printing
- display_echo_area
- display_echo_area_1
- resize_echo_area_exactly
- resize_mini_window_1
- resize_mini_window
- current_message
- current_message_1
- push_message
- restore_message
- pop_message_unwind
- check_message_stack
- clear_message_stack
- truncate_echo_area
- truncate_message_1
- set_message
- set_message_1
- clear_message
- clear_garbaged_frames
- echo_area_display
- window_buffer_changed
- mode_line_update_needed
- window_frozen_p
- format_mode_line_unwind_data
- unwind_format_mode_line
- store_mode_line_noprop_char
- store_mode_line_noprop
- gui_consider_frame_title
- needs_no_redisplay
- prepare_menu_bars
- update_menu_bar
- restore_selected_window
- restore_frame_selected_window
- update_tab_bar
- display_tab_bar
- build_desired_tab_bar_string
- display_tab_bar_line
- tab_bar_height
- redisplay_tab_bar
- tab_bar_item_info
- get_tab_bar_item
- handle_tab_bar_click
- note_tab_bar_highlight
- tty_get_tab_bar_item
- tty_handle_tab_bar_click
- update_tool_bar
- build_desired_tool_bar_string
- display_tool_bar_line
- tool_bar_height
- redisplay_tool_bar
- tool_bar_item_info
- get_tool_bar_item
- handle_tool_bar_click_with_device
- handle_tool_bar_click
- note_tool_bar_highlight
- hscroll_window_tree
- hscroll_windows
- debug_method_add
- text_outside_line_unchanged_p
- redisplay
- overlay_arrow_string_or_property
- overlay_arrow_in_current_buffer_p
- overlay_arrows_changed_p
- update_overlay_arrows
- overlay_arrow_at_row
- check_point_in_composition
- reconsider_clip_changes
- propagate_buffer_redisplay
- redisplay_internal
- unwind_redisplay_preserve_echo_area
- redisplay_preserve_echo_area
- unwind_redisplay
- unwind_display_working_on_window
- mark_window_display_accurate_1
- mark_window_display_accurate
- disp_char_vector
- block_buffer_flips
- unblock_buffer_flips
- buffer_flipping_blocked_p
- redisplay_windows
- redisplay_window_error
- redisplay_window_0
- redisplay_window_1
- update_redisplay_ticks
- set_cursor_from_row
- run_window_scroll_functions
- cursor_row_fully_visible_p
- try_scrolling
- compute_window_start_on_continuation_line
- try_cursor_movement
- set_vertical_scroll_bar
- set_horizontal_scroll_bar
- window_start_acceptable_p
- DEFUN
- redisplay_window
- try_window
- try_window_reusing_current_matrix
- find_last_row_displaying_text
- find_last_unchanged_at_beg_row
- find_first_unchanged_at_end_row
- sync_frame_with_window_matrix_rows
- row_containing_pos
- try_window_id
- dump_glyph_row
- dump_glyph
- dump_glyph_row
- DEFUN
- DEFUN
- DEFUN
- get_overlay_arrow_glyph_row
- insert_left_trunc_glyphs
- row_hash
- compute_line_metrics
- clear_position
- append_space_for_newline
- extend_face_to_end_of_line
- trailing_whitespace_p
- highlight_trailing_whitespace
- row_for_charpos_p
- cursor_row_p
- push_prefix_prop
- get_it_property
- get_line_prefix_it_property
- handle_line_prefix
- unproduce_glyphs
- find_row_edges
- display_count_lines_logically
- display_count_lines_visually
- maybe_produce_line_number
- should_produce_line_number
- row_text_area_empty
- display_line
- DEFUN
- DEFUN
- DEFUN
- display_menu_bar
- deep_copy_glyph_row
- display_tty_menu_item
- redisplay_mode_lines
- display_mode_lines
- display_mode_line
- move_elt_to_front
- safe_set_text_properties
- display_mode_element
- store_mode_line_string
- pint2str
- pint2hrstr
- decode_mode_spec_coding
- percent99
- decode_mode_spec
- count_lines
- display_count_lines
- display_string
- invisible_prop
- DEFUN
- calc_pixel_width_or_height
- get_font_ascent_descent
- dump_glyph_string
- init_glyph_string
- append_glyph_string_lists
- prepend_glyph_string_lists
- append_glyph_string
- get_char_face_and_encoding
- get_glyph_face_and_encoding
- get_char_glyph_code
- fill_composite_glyph_string
- fill_gstring_glyph_string
- fill_glyphless_glyph_string
- fill_glyph_string
- fill_image_glyph_string
- fill_xwidget_glyph_string
- fill_stretch_glyph_string
- get_per_char_metric
- normal_char_ascent_descent
- normal_char_height
- gui_get_glyph_overhangs
- left_overwritten
- left_overwriting
- right_overwritten
- right_overwriting
- set_glyph_string_background_width
- glyph_string_containing_background_width
- compute_overhangs_and_x
- draw_glyphs
- font_for_underline_metrics
- append_glyph
- append_composite_glyph
- take_vertical_position_into_account
- produce_image_glyph
- produce_xwidget_glyph
- append_stretch_glyph
- produce_stretch_glyph
- produce_special_glyphs
- calc_line_height_property
- append_glyphless_glyph
- produce_glyphless_glyph
- gui_produce_glyphs
- gui_write_glyphs
- gui_insert_glyphs
- gui_clear_end_of_line
- get_specified_cursor_type
- set_frame_cursor_types
- get_window_cursor_type
- notice_overwritten_cursor
- gui_fix_overlapping_area
- draw_phys_cursor_glyph
- erase_phys_cursor
- display_and_set_cursor
- update_window_cursor
- update_cursor_in_window_tree
- gui_update_cursor
- gui_clear_cursor
- draw_row_with_mouse_face
- show_mouse_face
- clear_mouse_face
- coords_in_mouse_face_p
- cursor_in_mouse_face_p
- rows_from_pos_range
- mouse_face_from_buffer_pos
- fast_find_string_pos
- mouse_face_from_string_pos
- on_hot_spot_p
- find_hot_spot
- define_frame_cursor1
- note_mode_line_or_margin_highlight
- note_mouse_highlight
- gui_clear_window_mouse_face
- cancel_mouse_face
- expose_area
- expose_line
- expose_overlaps
- phys_cursor_in_rect_p
- gui_draw_vertical_border
- gui_draw_right_divider
- gui_draw_bottom_divider
- expose_window
- expose_window_tree
- expose_frame
- gui_intersect_rectangles
- syms_of_xdisp
- init_xdisp
- show_hourglass
- start_hourglass
- cancel_hourglass
- adjust_glyph_width_for_mouse_face
- get_cursor_offset_for_mouse_face
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433 #include <config.h>
434 #include <stdlib.h>
435 #include <limits.h>
436 #include <math.h>
437
438 #include "lisp.h"
439 #include "atimer.h"
440 #include "composite.h"
441 #include "keyboard.h"
442 #include "sysstdio.h"
443 #include "systime.h"
444 #include "frame.h"
445 #include "window.h"
446 #include "termchar.h"
447 #include "dispextern.h"
448 #include "character.h"
449 #include "category.h"
450 #include "buffer.h"
451 #include "charset.h"
452 #include "indent.h"
453 #include "commands.h"
454 #include "keymap.h"
455 #include "disptab.h"
456 #include "termhooks.h"
457 #include "termopts.h"
458 #include "intervals.h"
459 #include "coding.h"
460 #include "region-cache.h"
461 #include "font.h"
462 #include "fontset.h"
463 #include "blockinput.h"
464 #include "xwidget.h"
465 #ifdef HAVE_WINDOW_SYSTEM
466 #include TERM_HEADER
467 #endif
468
469 #ifndef FRAME_OUTPUT_DATA
470 #define FRAME_OUTPUT_DATA(f) (NULL)
471 #endif
472
473 #define DISP_INFINITY 10000000
474
475
476 static Lisp_Object list_of_error;
477
478 #ifdef HAVE_WINDOW_SYSTEM
479
480
481
482
483 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(IT) \
484 (!NILP (Voverflow_newline_into_fringe) \
485 && FRAME_WINDOW_P ((IT)->f) \
486 && ((IT)->bidi_it.paragraph_dir == R2L \
487 ? (WINDOW_LEFT_FRINGE_WIDTH ((IT)->w) > 0) \
488 : (WINDOW_RIGHT_FRINGE_WIDTH ((IT)->w) > 0)) \
489 && (IT)->current_x == (IT)->last_visible_x)
490
491 #else
492 #define IT_OVERFLOW_NEWLINE_INTO_FRINGE(it) false
493 #endif
494
495
496
497
498
499 #define IT_DISPLAYING_WHITESPACE(it) \
500 ((it->what == IT_CHARACTER && (it->c == ' ' || it->c == '\t')) \
501 || ((STRINGP (it->string) \
502 && (SREF (it->string, IT_STRING_BYTEPOS (*it)) == ' ' \
503 || SREF (it->string, IT_STRING_BYTEPOS (*it)) == '\t')) \
504 || (it->s \
505 && (it->s[IT_BYTEPOS (*it)] == ' ' \
506 || it->s[IT_BYTEPOS (*it)] == '\t')) \
507 || (IT_BYTEPOS (*it) < ZV_BYTE \
508 && (*BYTE_POS_ADDR (IT_BYTEPOS (*it)) == ' ' \
509 || *BYTE_POS_ADDR (IT_BYTEPOS (*it)) == '\t'))))
510
511
512
513 #define NOT_AT_EOL '<'
514 #define NOT_AT_BOL '>'
515 #define LINE_BREAKABLE '|'
516
517 static bool
518 it_char_has_category(struct it *it, int cat)
519 {
520 int ch = 0;
521 if (it->what == IT_CHARACTER)
522 ch = it->c;
523 else if (STRINGP (it->string))
524 ch = SREF (it->string, IT_STRING_BYTEPOS (*it));
525 else if (it->s)
526 ch = it->s[IT_BYTEPOS (*it)];
527 else if (IT_BYTEPOS (*it) < ZV_BYTE)
528 ch = *BYTE_POS_ADDR (IT_BYTEPOS (*it));
529
530 if (ch == 0)
531 return false;
532 else
533 return CHAR_HAS_CATEGORY (ch, cat);
534 }
535
536
537 static bool
538 char_can_wrap_before (struct it *it)
539 {
540 if (!word_wrap_by_category)
541 return !IT_DISPLAYING_WHITESPACE (it);
542
543
544
545
546 int not_at_bol;
547 if (it->glyph_row && it->glyph_row->reversed_p)
548 not_at_bol = NOT_AT_EOL;
549 else
550 not_at_bol = NOT_AT_BOL;
551
552
553 return (!IT_DISPLAYING_WHITESPACE (it)
554
555 && !it_char_has_category (it, not_at_bol));
556 }
557
558
559 static bool
560 char_can_wrap_after (struct it *it)
561 {
562 if (!word_wrap_by_category)
563 return IT_DISPLAYING_WHITESPACE (it);
564
565
566
567
568 int not_at_eol;
569 if (it->glyph_row && it->glyph_row->reversed_p)
570 not_at_eol = NOT_AT_BOL;
571 else
572 not_at_eol = NOT_AT_EOL;
573
574 return (IT_DISPLAYING_WHITESPACE (it)
575
576 || (it_char_has_category (it, LINE_BREAKABLE)
577 && !it_char_has_category (it, not_at_eol)));
578 }
579
580 #undef IT_DISPLAYING_WHITESPACE
581 #undef NOT_AT_EOL
582 #undef NOT_AT_BOL
583 #undef LINE_BREAKABLE
584
585
586
587
588 static int
589 fill_column_indicator_column (struct it *it, int char_width)
590 {
591 if (display_fill_column_indicator
592 && !it->w->pseudo_window_p
593 && it->continuation_lines_width == 0
594 && CHARACTERP (Vdisplay_fill_column_indicator_character))
595 {
596 Lisp_Object col = (EQ (Vdisplay_fill_column_indicator_column, Qt)
597 ? BVAR (current_buffer, fill_column)
598 : Vdisplay_fill_column_indicator_column);
599
600
601
602 if (RANGED_FIXNUMP (0, col, INT_MAX))
603 {
604 int icol = XFIXNUM (col);
605 if (!INT_MULTIPLY_WRAPV (char_width, icol, &icol)
606 && !INT_ADD_WRAPV (it->lnum_pixel_width, icol, &icol))
607 return icol;
608 }
609 }
610 return -1;
611 }
612
613
614
615 bool noninteractive_need_newline;
616
617
618
619 static bool message_log_need_newline;
620
621
622
623
624 static Lisp_Object message_dolog_marker1;
625 static Lisp_Object message_dolog_marker2;
626 static Lisp_Object message_dolog_marker3;
627
628
629
630
631
632
633 static struct text_pos this_line_start_pos;
634
635
636
637
638 static struct text_pos this_line_end_pos;
639
640
641
642 static int this_line_vpos;
643 static int this_line_y;
644 static int this_line_pixel_height;
645
646
647
648
649 static int this_line_start_x;
650
651
652
653
654
655 static struct text_pos this_line_min_pos;
656
657
658
659 static struct buffer *this_line_buffer;
660
661
662
663 static bool overlay_arrow_seen;
664
665
666
667 static Lisp_Object default_invis_vector[3];
668
669
670
671
672
673 Lisp_Object echo_area_window;
674
675
676
677
678 static Lisp_Object Vmessage_stack;
679
680
681
682
683 static bool message_enable_multibyte;
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715 int windows_or_buffers_changed;
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736 int update_mode_lines;
737
738
739
740
741 static bool line_number_displayed;
742
743
744
745
746 Lisp_Object echo_area_buffer[2];
747
748
749
750 static Lisp_Object echo_buffer[2];
751
752
753
754 static Lisp_Object Vwith_echo_area_save_vector;
755
756
757
758
759 static bool display_last_displayed_message_p;
760
761
762
763
764 static bool message_buf_print;
765
766
767
768
769 static bool message_cleared_p;
770
771
772
773
774 #define MAX_SCRATCH_GLYPHS 100
775 static struct glyph_row scratch_glyph_row;
776 static struct glyph scratch_glyphs[MAX_SCRATCH_GLYPHS];
777
778
779
780 static int last_height;
781
782
783
784 bool help_echo_showing_p;
785
786
787
788
789
790
791
792 #define TEXT_PROP_DISTANCE_LIMIT 100
793
794
795
796
797
798
799
800
801 #define SAVE_IT(ITCOPY, ITORIG, CACHE) \
802 do { \
803 if (CACHE) \
804 bidi_unshelve_cache (CACHE, true); \
805 ITCOPY = ITORIG; \
806 CACHE = bidi_shelve_cache (); \
807 } while (false)
808
809 #define RESTORE_IT(pITORIG, pITCOPY, CACHE) \
810 do { \
811 if (pITORIG != pITCOPY) \
812 *(pITORIG) = *(pITCOPY); \
813 bidi_unshelve_cache (CACHE, false); \
814 CACHE = NULL; \
815 } while (false)
816
817
818 enum { REDISPLAY_SOME = 2};
819
820 static bool calc_pixel_width_or_height (double *, struct it *, Lisp_Object,
821 struct font *, bool, int *);
822
823 void
824 redisplay_other_windows (void)
825 {
826 if (!windows_or_buffers_changed)
827 windows_or_buffers_changed = REDISPLAY_SOME;
828 }
829
830 void
831 wset_redisplay (struct window *w)
832 {
833
834 if (!BASE_EQ (make_lisp_ptr (w, Lisp_Vectorlike), selected_window))
835 redisplay_other_windows ();
836 w->redisplay = true;
837 }
838
839 void
840 fset_redisplay (struct frame *f)
841 {
842 redisplay_other_windows ();
843 f->redisplay = true;
844 }
845
846 void
847 bset_redisplay (struct buffer *b)
848 {
849 int count = buffer_window_count (b);
850 if (count > 0)
851 {
852
853 if (count > 1 || b != XBUFFER (XWINDOW (selected_window)->contents))
854 redisplay_other_windows ();
855
856
857
858 b->text->redisplay = true;
859 }
860 }
861
862 void
863 bset_update_mode_line (struct buffer *b)
864 {
865 if (!update_mode_lines)
866 update_mode_lines = REDISPLAY_SOME;
867 b->text->redisplay = true;
868 }
869
870 void
871 wset_update_mode_line (struct window *w)
872 {
873 w->update_mode_line = true;
874
875
876
877
878
879
880 wset_redisplay (w);
881 }
882
883 DEFUN ("set-buffer-redisplay", Fset_buffer_redisplay,
884 Sset_buffer_redisplay, 4, 4, 0,
885 doc:
886 )
887 (Lisp_Object symbol, Lisp_Object newval, Lisp_Object op, Lisp_Object where)
888 {
889 bset_update_mode_line (current_buffer);
890 current_buffer->prevent_redisplay_optimizations_p = true;
891 return Qnil;
892 }
893
894
895
896
897
898 #ifdef GLYPH_DEBUG
899 extern bool trace_redisplay_p EXTERNALLY_VISIBLE;
900 bool trace_redisplay_p;
901 #else
902 enum { trace_redisplay_p = false };
903 #endif
904 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
905 redisplay_trace (char const *fmt, ...)
906 {
907 if (trace_redisplay_p)
908 {
909 va_list ap;
910 va_start (ap, fmt);
911 vprintf (fmt, ap);
912 va_end (ap);
913 }
914 }
915
916 #ifdef DEBUG_TRACE_MOVE
917 extern bool trace_move EXTERNALLY_VISIBLE;
918 bool trace_move;
919 #else
920 enum { trace_move = false };
921 #endif
922 static void ATTRIBUTE_FORMAT_PRINTF (1, 2)
923 move_trace (char const *fmt, ...)
924 {
925 if (trace_move)
926 {
927 va_list ap;
928 va_start (ap, fmt);
929 vprintf (fmt, ap);
930 va_end (ap);
931 }
932 }
933
934
935
936 static struct buffer *displayed_buffer;
937
938
939
940 enum prop_handled
941 {
942 HANDLED_NORMALLY,
943 HANDLED_RECOMPUTE_PROPS,
944 HANDLED_OVERLAY_STRING_CONSUMED,
945 HANDLED_RETURN
946 };
947
948
949
950
951 struct props
952 {
953
954 short name;
955
956
957 enum prop_idx idx;
958
959
960
961 enum prop_handled (*handler) (struct it *it);
962 };
963
964 static enum prop_handled handle_face_prop (struct it *);
965 static enum prop_handled handle_invisible_prop (struct it *);
966 static enum prop_handled handle_display_prop (struct it *);
967 static enum prop_handled handle_composition_prop (struct it *);
968 static enum prop_handled handle_overlay_change (struct it *);
969 static enum prop_handled handle_fontified_prop (struct it *);
970
971
972
973 static struct props it_props[] =
974 {
975 {SYMBOL_INDEX (Qfontified), FONTIFIED_PROP_IDX, handle_fontified_prop},
976
977
978 {SYMBOL_INDEX (Qface), FACE_PROP_IDX, handle_face_prop},
979 {SYMBOL_INDEX (Qdisplay), DISPLAY_PROP_IDX, handle_display_prop},
980 {SYMBOL_INDEX (Qinvisible), INVISIBLE_PROP_IDX, handle_invisible_prop},
981 {SYMBOL_INDEX (Qcomposition), COMPOSITION_PROP_IDX, handle_composition_prop},
982 {0, 0, NULL}
983 };
984
985
986
987 enum move_it_result
988 {
989
990 MOVE_UNDEFINED,
991
992
993 MOVE_POS_MATCH_OR_ZV,
994
995
996 MOVE_X_REACHED,
997
998
999
1000 MOVE_LINE_CONTINUED,
1001
1002
1003
1004 MOVE_LINE_TRUNCATED,
1005
1006
1007 MOVE_NEWLINE_OR_CR
1008 };
1009
1010
1011
1012
1013
1014
1015 #define CLEAR_FACE_CACHE_COUNT 500
1016 static int clear_face_cache_count;
1017
1018
1019
1020 #ifdef HAVE_WINDOW_SYSTEM
1021 #define CLEAR_IMAGE_CACHE_COUNT 101
1022 static int clear_image_cache_count;
1023
1024
1025 static struct glyph_slice null_glyph_slice = { 0, 0, 0, 0 };
1026 #endif
1027
1028
1029
1030 bool redisplaying_p;
1031
1032
1033
1034
1035
1036
1037
1038
1039 bool display_working_on_window_p;
1040
1041
1042
1043
1044 Lisp_Object help_echo_string;
1045 Lisp_Object help_echo_window;
1046 Lisp_Object help_echo_object;
1047 ptrdiff_t help_echo_pos;
1048
1049
1050
1051 Lisp_Object previous_help_echo_string;
1052
1053
1054
1055 #ifdef HAVE_WINDOW_SYSTEM
1056
1057
1058 static bool hourglass_shown_p;
1059
1060
1061
1062 static struct atimer *hourglass_atimer;
1063
1064 #endif
1065
1066
1067
1068 #define DEFAULT_HOURGLASS_DELAY 1
1069
1070 #ifdef HAVE_WINDOW_SYSTEM
1071
1072
1073 #define THIN_SPACE_WIDTH 1
1074
1075 #endif
1076
1077
1078
1079 static void setup_for_ellipsis (struct it *, int);
1080 static void set_iterator_to_next (struct it *, bool);
1081 static void mark_window_display_accurate_1 (struct window *, bool);
1082 static bool row_for_charpos_p (struct glyph_row *, ptrdiff_t);
1083 static bool cursor_row_p (struct glyph_row *);
1084 static int redisplay_mode_lines (Lisp_Object, bool);
1085
1086 static void handle_line_prefix (struct it *);
1087
1088 static void handle_stop_backwards (struct it *, ptrdiff_t);
1089 static void unwind_with_echo_area_buffer (Lisp_Object);
1090 static Lisp_Object with_echo_area_buffer_unwind_data (struct window *);
1091 static bool current_message_1 (void *, Lisp_Object);
1092 static bool truncate_message_1 (void *, Lisp_Object);
1093 static void set_message (Lisp_Object);
1094 static bool set_message_1 (void *, Lisp_Object);
1095 static bool display_echo_area_1 (void *, Lisp_Object);
1096 static bool resize_mini_window_1 (void *, Lisp_Object);
1097 static void unwind_redisplay (void);
1098 static void extend_face_to_end_of_line (struct it *);
1099 static intmax_t message_log_check_duplicate (ptrdiff_t, ptrdiff_t);
1100 static void push_it (struct it *, struct text_pos *);
1101 static void iterate_out_of_display_property (struct it *);
1102 static void pop_it (struct it *);
1103 static void redisplay_internal (void);
1104 static void echo_area_display (bool);
1105 static void block_buffer_flips (void);
1106 static void unblock_buffer_flips (void);
1107 static void redisplay_windows (Lisp_Object);
1108 static void redisplay_window (Lisp_Object, bool);
1109 static Lisp_Object redisplay_window_error (Lisp_Object);
1110 static Lisp_Object redisplay_window_0 (Lisp_Object);
1111 static Lisp_Object redisplay_window_1 (Lisp_Object);
1112 static bool set_cursor_from_row (struct window *, struct glyph_row *,
1113 struct glyph_matrix *, ptrdiff_t, ptrdiff_t,
1114 int, int);
1115 static bool cursor_row_fully_visible_p (struct window *, bool, bool, bool);
1116 static bool update_menu_bar (struct frame *, bool, bool);
1117 static bool try_window_reusing_current_matrix (struct window *);
1118 static int try_window_id (struct window *);
1119 static void maybe_produce_line_number (struct it *);
1120 static bool should_produce_line_number (struct it *);
1121 static bool display_line (struct it *, int);
1122 static int display_mode_lines (struct window *);
1123 static int display_mode_line (struct window *, enum face_id, Lisp_Object);
1124 static int display_mode_element (struct it *, int, int, int, Lisp_Object,
1125 Lisp_Object, bool);
1126 static int store_mode_line_string (const char *, Lisp_Object, bool, int, int,
1127 Lisp_Object);
1128 static const char *decode_mode_spec (struct window *, int, int, Lisp_Object *);
1129 static void display_menu_bar (struct window *);
1130 static void display_tab_bar (struct window *);
1131 static void update_tab_bar (struct frame *, bool);
1132 static ptrdiff_t display_count_lines (ptrdiff_t, ptrdiff_t, ptrdiff_t,
1133 ptrdiff_t *);
1134 static void pint2str (register char *, register int, register ptrdiff_t);
1135
1136 static int display_string (const char *, Lisp_Object, Lisp_Object,
1137 ptrdiff_t, ptrdiff_t, struct it *, int, int, int,
1138 int);
1139 static void compute_line_metrics (struct it *);
1140 static bool get_overlay_strings (struct it *, ptrdiff_t);
1141 static bool get_overlay_strings_1 (struct it *, ptrdiff_t, bool);
1142 static void next_overlay_string (struct it *);
1143 static void reseat (struct it *, struct text_pos, bool);
1144 static void reseat_1 (struct it *, struct text_pos, bool);
1145 static bool next_element_from_display_vector (struct it *);
1146 static bool next_element_from_string (struct it *);
1147 static bool next_element_from_c_string (struct it *);
1148 static bool next_element_from_buffer (struct it *);
1149 static bool next_element_from_composition (struct it *);
1150 static bool next_element_from_image (struct it *);
1151 static bool next_element_from_stretch (struct it *);
1152 static bool next_element_from_xwidget (struct it *);
1153 static void load_overlay_strings (struct it *, ptrdiff_t);
1154 static bool get_next_display_element (struct it *);
1155 static enum move_it_result
1156 move_it_in_display_line_to (struct it *, ptrdiff_t, int,
1157 enum move_operation_enum);
1158 static void get_visually_first_element (struct it *);
1159 static void compute_stop_pos (struct it *);
1160 static int face_before_or_after_it_pos (struct it *, bool);
1161 static int handle_display_spec (struct it *, Lisp_Object, Lisp_Object,
1162 Lisp_Object, struct text_pos *, ptrdiff_t, bool);
1163 static int handle_single_display_spec (struct it *, Lisp_Object, Lisp_Object,
1164 Lisp_Object, struct text_pos *,
1165 ptrdiff_t, int, bool, bool);
1166 static int underlying_face_id (const struct it *);
1167
1168 #define face_before_it_pos(IT) face_before_or_after_it_pos (IT, true)
1169 #define face_after_it_pos(IT) face_before_or_after_it_pos (IT, false)
1170
1171 #ifdef HAVE_WINDOW_SYSTEM
1172
1173 static void update_tool_bar (struct frame *, bool);
1174 static void gui_draw_bottom_divider (struct window *w);
1175 static void notice_overwritten_cursor (struct window *,
1176 enum glyph_row_area,
1177 int, int, int, int);
1178 static int normal_char_height (struct font *, int);
1179 static void normal_char_ascent_descent (struct font *, int, int *, int *);
1180
1181 static void append_stretch_glyph (struct it *, Lisp_Object,
1182 int, int, int);
1183
1184 static Lisp_Object get_it_property (struct it *, Lisp_Object);
1185 static Lisp_Object calc_line_height_property (struct it *, Lisp_Object,
1186 struct font *, int, bool);
1187 static int adjust_glyph_width_for_mouse_face (struct glyph *,
1188 struct glyph_row *,
1189 struct window *, struct face *,
1190 struct face *);
1191 static void get_cursor_offset_for_mouse_face (struct window *w,
1192 struct glyph_row *row,
1193 int *offset);
1194 #endif
1195
1196 static void produce_special_glyphs (struct it *, enum display_element_type);
1197 static void show_mouse_face (Mouse_HLInfo *, enum draw_glyphs_face);
1198 static bool coords_in_mouse_face_p (struct window *, int, int);
1199 static void reset_box_start_end_flags (struct it *);
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213 int
1214 window_text_bottom_y (struct window *w)
1215 {
1216 int height = WINDOW_PIXEL_HEIGHT (w);
1217
1218 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1219
1220 if (window_wants_mode_line (w))
1221 height -= CURRENT_MODE_LINE_HEIGHT (w);
1222
1223 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1224
1225 return height;
1226 }
1227
1228
1229
1230
1231
1232 int
1233 window_box_width (struct window *w, enum glyph_row_area area)
1234 {
1235 int width = w->pixel_width;
1236
1237 if (!w->pseudo_window_p)
1238 {
1239 width -= WINDOW_SCROLL_BAR_AREA_WIDTH (w);
1240 width -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
1241
1242 if (area == TEXT_AREA)
1243 width -= (WINDOW_MARGINS_WIDTH (w)
1244 + WINDOW_FRINGES_WIDTH (w));
1245 else if (area == LEFT_MARGIN_AREA)
1246 width = WINDOW_LEFT_MARGIN_WIDTH (w);
1247 else if (area == RIGHT_MARGIN_AREA)
1248 width = WINDOW_RIGHT_MARGIN_WIDTH (w);
1249 }
1250
1251
1252
1253 return max (0, width);
1254 }
1255
1256
1257
1258
1259
1260 int
1261 window_box_height (struct window *w)
1262 {
1263 struct frame *f = XFRAME (w->frame);
1264 int height = WINDOW_PIXEL_HEIGHT (w);
1265
1266 eassert (height >= 0);
1267
1268 height -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
1269 height -= WINDOW_SCROLL_BAR_AREA_HEIGHT (w);
1270
1271
1272
1273
1274
1275
1276
1277 if (window_wants_mode_line (w))
1278 {
1279 if (w->mode_line_height >= 0)
1280 height -= w->mode_line_height;
1281 else
1282 {
1283 struct glyph_row *ml_row
1284 = (w->current_matrix && w->current_matrix->rows
1285 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
1286 : 0);
1287 if (ml_row && ml_row->mode_line_p)
1288 height -= ml_row->height;
1289 else
1290 height -= estimate_mode_line_height
1291 (f, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w));
1292 }
1293 }
1294
1295 if (window_wants_tab_line (w))
1296 {
1297 if (w->tab_line_height >= 0)
1298 height -= w->tab_line_height;
1299 else
1300 {
1301 struct glyph_row *tl_row
1302 = (w->current_matrix && w->current_matrix->rows
1303 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
1304 : 0);
1305 if (tl_row && tl_row->mode_line_p)
1306 height -= tl_row->height;
1307 else
1308 height -= estimate_mode_line_height (f, TAB_LINE_FACE_ID);
1309 }
1310 }
1311
1312 if (window_wants_header_line (w))
1313 {
1314 if (w->header_line_height >= 0)
1315 height -= w->header_line_height;
1316 else
1317 {
1318 struct glyph_row *hl_row
1319 = (w->current_matrix && w->current_matrix->rows
1320 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
1321 : 0);
1322 if (hl_row && hl_row->mode_line_p)
1323 height -= hl_row->height;
1324 else
1325 height -= estimate_mode_line_height (f, HEADER_LINE_FACE_ID);
1326 }
1327 }
1328
1329
1330
1331 return max (0, height);
1332 }
1333
1334
1335
1336
1337
1338 int
1339 window_box_left_offset (struct window *w, enum glyph_row_area area)
1340 {
1341 int x;
1342
1343 if (w->pseudo_window_p)
1344 return 0;
1345
1346 x = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
1347
1348 if (area == TEXT_AREA)
1349 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1350 + window_box_width (w, LEFT_MARGIN_AREA));
1351 else if (area == RIGHT_MARGIN_AREA)
1352 x += (WINDOW_LEFT_FRINGE_WIDTH (w)
1353 + window_box_width (w, LEFT_MARGIN_AREA)
1354 + window_box_width (w, TEXT_AREA)
1355 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
1356 ? 0
1357 : WINDOW_RIGHT_FRINGE_WIDTH (w)));
1358 else if (area == LEFT_MARGIN_AREA
1359 && WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w))
1360 x += WINDOW_LEFT_FRINGE_WIDTH (w);
1361
1362
1363 return min (x, w->pixel_width);
1364 }
1365
1366
1367
1368
1369
1370
1371 static int
1372 window_box_right_offset (struct window *w, enum glyph_row_area area)
1373 {
1374
1375 return min (window_box_left_offset (w, area) + window_box_width (w, area),
1376 w->pixel_width);
1377 }
1378
1379
1380
1381
1382
1383 int
1384 window_box_left (struct window *w, enum glyph_row_area area)
1385 {
1386 struct frame *f = XFRAME (w->frame);
1387 int x;
1388
1389 if (w->pseudo_window_p)
1390 return FRAME_INTERNAL_BORDER_WIDTH (f);
1391
1392 x = (WINDOW_LEFT_EDGE_X (w)
1393 + window_box_left_offset (w, area));
1394
1395 return x;
1396 }
1397
1398
1399
1400
1401
1402
1403 int
1404 window_box_right (struct window *w, enum glyph_row_area area)
1405 {
1406 return window_box_left (w, area) + window_box_width (w, area);
1407 }
1408
1409
1410
1411
1412
1413
1414
1415
1416 void
1417 window_box (struct window *w, enum glyph_row_area area, int *box_x,
1418 int *box_y, int *box_width, int *box_height)
1419 {
1420 if (box_width)
1421 *box_width = window_box_width (w, area);
1422 if (box_height)
1423 *box_height = window_box_height (w);
1424 if (box_x)
1425 *box_x = window_box_left (w, area);
1426 if (box_y)
1427 {
1428 *box_y = WINDOW_TOP_EDGE_Y (w);
1429 if (window_wants_tab_line (w))
1430 *box_y += CURRENT_TAB_LINE_HEIGHT (w);
1431 if (window_wants_header_line (w))
1432 *box_y += CURRENT_HEADER_LINE_HEIGHT (w);
1433 }
1434 }
1435
1436 #ifdef HAVE_WINDOW_SYSTEM
1437
1438
1439
1440
1441
1442
1443
1444
1445 static void
1446 window_box_edges (struct window *w, int *top_left_x, int *top_left_y,
1447 int *bottom_right_x, int *bottom_right_y)
1448 {
1449 window_box (w, ANY_AREA, top_left_x, top_left_y,
1450 bottom_right_x, bottom_right_y);
1451 *bottom_right_x += *top_left_x;
1452 *bottom_right_y += *top_left_y;
1453 }
1454
1455 #endif
1456
1457
1458
1459
1460
1461
1462
1463
1464 int
1465 line_bottom_y (struct it *it)
1466 {
1467 int line_height = it->max_ascent + it->max_descent;
1468 int line_top_y = it->current_y;
1469
1470 if (line_height == 0)
1471 {
1472 if (last_height)
1473 line_height = last_height;
1474 else if (IT_CHARPOS (*it) < ZV)
1475 {
1476 move_it_by_lines (it, 1);
1477 line_height = (it->max_ascent || it->max_descent
1478 ? it->max_ascent + it->max_descent
1479 : last_height);
1480 }
1481 else
1482 {
1483 struct glyph_row *row = it->glyph_row;
1484
1485
1486 it->glyph_row = NULL;
1487 it->what = IT_CHARACTER;
1488 it->c = ' ';
1489 it->len = 1;
1490 PRODUCE_GLYPHS (it);
1491 line_height = it->ascent + it->descent;
1492 it->glyph_row = row;
1493 }
1494 }
1495
1496 return line_top_y + line_height;
1497 }
1498
1499 DEFUN ("line-pixel-height", Fline_pixel_height,
1500 Sline_pixel_height, 0, 0, 0,
1501 doc:
1502
1503 )
1504 (void)
1505 {
1506 struct it it;
1507 struct text_pos pt;
1508 struct window *w = XWINDOW (selected_window);
1509 struct buffer *old_buffer = NULL;
1510 Lisp_Object result;
1511
1512 if (XBUFFER (w->contents) != current_buffer)
1513 {
1514 old_buffer = current_buffer;
1515 set_buffer_internal_1 (XBUFFER (w->contents));
1516 }
1517 SET_TEXT_POS (pt, PT, PT_BYTE);
1518 void *itdata = bidi_shelve_cache ();
1519 start_display (&it, w, pt);
1520
1521
1522
1523 move_it_by_lines (&it, 0);
1524 it.vpos = it.current_y = 0;
1525 last_height = 0;
1526 result = make_fixnum (line_bottom_y (&it));
1527 if (old_buffer)
1528 set_buffer_internal_1 (old_buffer);
1529
1530 bidi_unshelve_cache (itdata, false);
1531 return result;
1532 }
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548 int
1549 default_line_pixel_height (struct window *w)
1550 {
1551 struct frame *f = WINDOW_XFRAME (w);
1552 int height = FRAME_LINE_HEIGHT (f);
1553
1554 if (!FRAME_INITIAL_P (f) && BUFFERP (w->contents))
1555 {
1556 struct buffer *b = XBUFFER (w->contents);
1557 Lisp_Object val = BVAR (b, extra_line_spacing);
1558
1559 if (NILP (val))
1560 val = BVAR (&buffer_defaults, extra_line_spacing);
1561 if (!NILP (val))
1562 {
1563 if (RANGED_FIXNUMP (0, val, INT_MAX))
1564 height += XFIXNAT (val);
1565 else if (FLOATP (val))
1566 {
1567 int addon = XFLOAT_DATA (val) * height + 0.5;
1568
1569 if (addon >= 0)
1570 height += addon;
1571 }
1572 }
1573 else
1574 height += f->extra_line_spacing;
1575 }
1576
1577 return height;
1578 }
1579
1580
1581
1582 static Lisp_Object
1583 string_from_display_spec (Lisp_Object spec)
1584 {
1585 if (VECTORP (spec))
1586 {
1587 for (ptrdiff_t i = 0; i < ASIZE (spec); i++)
1588 if (STRINGP (AREF (spec, i)))
1589 return AREF (spec, i);
1590 }
1591 else
1592 {
1593 for (; CONSP (spec); spec = XCDR (spec))
1594 if (STRINGP (XCAR (spec)))
1595 return XCAR (spec);
1596 }
1597 return spec;
1598 }
1599
1600
1601
1602
1603
1604 static int
1605 window_hscroll_limited (struct window *w, struct frame *f)
1606 {
1607 ptrdiff_t window_hscroll = w->hscroll;
1608 int window_text_width = window_box_width (w, TEXT_AREA);
1609 int colwidth = FRAME_COLUMN_WIDTH (f);
1610
1611 if (window_hscroll > (INT_MAX - window_text_width) / colwidth - 1)
1612 window_hscroll = (INT_MAX - window_text_width) / colwidth - 1;
1613
1614 return window_hscroll;
1615 }
1616
1617
1618
1619
1620
1621 static void
1622 reset_box_start_end_flags (struct it *it)
1623 {
1624
1625
1626 if (it->area == TEXT_AREA
1627
1628 && !(it->what == IT_IMAGE && it->image_id < 0))
1629 {
1630
1631
1632
1633
1634 if (it->face_box_p)
1635 it->start_of_box_run_p = false;
1636 it->end_of_box_run_p = false;
1637 }
1638 }
1639
1640
1641
1642
1643
1644
1645
1646 bool
1647 pos_visible_p (struct window *w, ptrdiff_t charpos, int *x, int *y,
1648 int *rtop, int *rbot, int *rowh, int *vpos)
1649 {
1650 struct it it;
1651 void *itdata = bidi_shelve_cache ();
1652 struct text_pos top;
1653 bool visible_p = false;
1654 struct buffer *old_buffer = NULL;
1655 bool r2l = false;
1656
1657 if (FRAME_INITIAL_P (XFRAME (WINDOW_FRAME (w))))
1658 return visible_p;
1659
1660 if (XBUFFER (w->contents) != current_buffer)
1661 {
1662 old_buffer = current_buffer;
1663 set_buffer_internal_1 (XBUFFER (w->contents));
1664 }
1665
1666 SET_TEXT_POS_FROM_MARKER (top, w->start);
1667
1668
1669
1670
1671 if (CHARPOS (top) > ZV || CHARPOS (top) < BEGV)
1672 SET_TEXT_POS (top, BEGV, BEGV_BYTE);
1673
1674
1675
1676 if (charpos >= 0 && CHARPOS (top) > charpos)
1677 return visible_p;
1678
1679
1680
1681
1682
1683
1684
1685
1686 int prev_mode_line_height = w->mode_line_height;
1687 int prev_header_line_height = w->header_line_height;
1688 int prev_tab_line_height = w->tab_line_height;
1689
1690 if (window_wants_mode_line (w))
1691 {
1692 Lisp_Object window_mode_line_format
1693 = window_parameter (w, Qmode_line_format);
1694
1695 w->mode_line_height
1696 = display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
1697 NILP (window_mode_line_format)
1698 ? BVAR (current_buffer, mode_line_format)
1699 : window_mode_line_format);
1700 }
1701
1702 if (window_wants_tab_line (w))
1703 {
1704 Lisp_Object window_tab_line_format
1705 = window_parameter (w, Qtab_line_format);
1706
1707 w->tab_line_height
1708 = display_mode_line (w, TAB_LINE_FACE_ID,
1709 NILP (window_tab_line_format)
1710 ? BVAR (current_buffer, tab_line_format)
1711 : window_tab_line_format);
1712 }
1713
1714 if (window_wants_header_line (w))
1715 {
1716 Lisp_Object window_header_line_format
1717 = window_parameter (w, Qheader_line_format);
1718
1719 w->header_line_height
1720 = display_mode_line (w, HEADER_LINE_FACE_ID,
1721 NILP (window_header_line_format)
1722 ? BVAR (current_buffer, header_line_format)
1723 : window_header_line_format);
1724 }
1725
1726 start_display (&it, w, top);
1727 move_it_to (&it, charpos, -1, it.last_visible_y - 1, -1,
1728 (charpos >= 0 ? MOVE_TO_POS : 0) | MOVE_TO_Y);
1729
1730
1731
1732 if (!NILP (Vdisplay_line_numbers)
1733 && it.current_x >= it.first_visible_x
1734 && IT_CHARPOS (it) == charpos
1735 && !it.line_number_produced_p)
1736 {
1737
1738
1739
1740 if (!it.lnum_pixel_width)
1741 {
1742 struct it it2;
1743 void *it2data = NULL;
1744
1745 SAVE_IT (it2, it, it2data);
1746 move_it_by_lines (&it, 1);
1747 it2.lnum_pixel_width = it.lnum_pixel_width;
1748 RESTORE_IT (&it, &it2, it2data);
1749 }
1750 it.current_x += it.lnum_pixel_width;
1751 }
1752
1753 if (charpos >= 0
1754 && (((!it.bidi_p || it.bidi_it.scan_dir != -1)
1755 && IT_CHARPOS (it) >= charpos)
1756
1757
1758
1759 || (it.bidi_p && it.bidi_it.scan_dir == -1
1760 && IT_CHARPOS (it) <= charpos)))
1761 {
1762
1763
1764
1765
1766
1767
1768 int top_x = it.current_x;
1769 int top_y = it.current_y;
1770 int window_top_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
1771 int bottom_y;
1772 struct it save_it;
1773 void *save_it_data = NULL;
1774
1775
1776 SAVE_IT (save_it, it, save_it_data);
1777 last_height = 0;
1778 bottom_y = line_bottom_y (&it);
1779 if (top_y < window_top_y)
1780 visible_p = bottom_y > window_top_y;
1781 else if (top_y < it.last_visible_y)
1782 visible_p = true;
1783 if (bottom_y >= it.last_visible_y
1784 && it.bidi_p && it.bidi_it.scan_dir == -1
1785 && IT_CHARPOS (it) < charpos)
1786 {
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797 int ten_more_lines = 10 * default_line_pixel_height (w);
1798
1799 move_it_to (&it, charpos, -1, bottom_y + ten_more_lines, -1,
1800 MOVE_TO_POS | MOVE_TO_Y);
1801 if (it.current_y > top_y)
1802 visible_p = false;
1803
1804 }
1805 RESTORE_IT (&it, &save_it, save_it_data);
1806 if (visible_p)
1807 {
1808 if (it.method == GET_FROM_DISPLAY_VECTOR)
1809 {
1810
1811
1812 if (charpos < 2 || top.charpos >= charpos)
1813 top_x = it.glyph_row->x;
1814 else
1815 {
1816 struct it it2, it2_prev;
1817
1818
1819
1820
1821
1822
1823 start_display (&it2, w, top);
1824 it2.glyph_row = NULL;
1825 move_it_to (&it2, charpos - 1, -1, -1, -1, MOVE_TO_POS);
1826
1827
1828
1829
1830 if (IT_CHARPOS (it2) != charpos - 1)
1831 it2_prev = it2;
1832 else
1833 {
1834
1835
1836
1837 do {
1838 get_next_display_element (&it2);
1839 PRODUCE_GLYPHS (&it2);
1840 it2_prev = it2;
1841 set_iterator_to_next (&it2, true);
1842 } while (it2.method == GET_FROM_DISPLAY_VECTOR
1843 && IT_CHARPOS (it2) < charpos);
1844 }
1845 if (ITERATOR_AT_END_OF_LINE_P (&it2_prev)
1846 || it2_prev.current_x > it2_prev.last_visible_x)
1847 top_x = it.glyph_row->x;
1848 else
1849 {
1850 top_x = it2_prev.current_x;
1851 top_y = it2_prev.current_y;
1852 }
1853 }
1854 }
1855 else if (IT_CHARPOS (it) != charpos)
1856 {
1857 Lisp_Object cpos = make_fixnum (charpos);
1858 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
1859 Lisp_Object string = string_from_display_spec (spec);
1860 struct text_pos tpos;
1861 bool newline_in_string
1862 = (STRINGP (string)
1863 && memchr (SDATA (string), '\n', SBYTES (string)));
1864
1865 SET_TEXT_POS (tpos, charpos, CHAR_TO_BYTE (charpos));
1866 bool replacing_spec_p
1867 = (!NILP (spec)
1868 && handle_display_spec (NULL, spec, Qnil, Qnil, &tpos,
1869 charpos, FRAME_WINDOW_P (it.f)));
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886 if (replacing_spec_p)
1887 {
1888 Lisp_Object startpos, endpos;
1889 EMACS_INT start, end;
1890 struct it it3;
1891
1892
1893
1894 endpos =
1895 Fnext_single_char_property_change (cpos, Qdisplay,
1896 Qnil, Qnil);
1897 startpos =
1898 Fprevious_single_char_property_change (endpos, Qdisplay,
1899 Qnil, Qnil);
1900 start = XFIXNAT (startpos);
1901 end = XFIXNAT (endpos);
1902
1903
1904 start_display (&it3, w, top);
1905 if (start > CHARPOS (top))
1906 move_it_to (&it3, start - 1, -1, -1, -1, MOVE_TO_POS);
1907
1908
1909
1910
1911 if (it3.method == GET_FROM_BUFFER
1912 && (it3.c == '\n'
1913 || FETCH_BYTE (IT_BYTEPOS (it3)) == '\n'))
1914 move_it_by_lines (&it3, 1);
1915 else if (move_it_in_display_line_to (&it3, -1,
1916 it3.current_x
1917 + it3.pixel_width,
1918 MOVE_TO_X)
1919 == MOVE_LINE_CONTINUED)
1920 {
1921 move_it_by_lines (&it3, 1);
1922
1923
1924
1925 if (it3.line_wrap == WORD_WRAP)
1926 move_it_by_lines (&it3, -1);
1927 }
1928
1929
1930
1931 top_y = it3.current_y;
1932 if (it3.bidi_p)
1933 {
1934
1935
1936
1937
1938
1939 start_display (&it3, w, top);
1940 move_it_to (&it3, end + 1, -1, -1, -1, MOVE_TO_POS);
1941 if (it3.current_y < top_y)
1942 top_y = it3.current_y;
1943 }
1944
1945
1946
1947 start_display (&it3, w, top);
1948 it3.glyph_row = NULL;
1949 move_it_to (&it3, -1, 0, top_y, -1, MOVE_TO_X | MOVE_TO_Y);
1950
1951
1952
1953
1954
1955
1956
1957 bool it3_moved = false;
1958 int top_x_before_string = it3.current_x;
1959
1960
1961
1962
1963
1964 while (get_next_display_element (&it3))
1965 {
1966 if (!EQ (it3.object, string))
1967 top_x_before_string = it3.current_x;
1968 PRODUCE_GLYPHS (&it3);
1969 if ((it3.bidi_it.scan_dir == 1
1970 && IT_CHARPOS (it3) >= charpos)
1971 || (it3.bidi_it.scan_dir == -1
1972 && IT_CHARPOS (it3) <= charpos)
1973 || ITERATOR_AT_END_OF_LINE_P (&it3))
1974 break;
1975 it3_moved = true;
1976 set_iterator_to_next (&it3, false);
1977 }
1978 top_x = it3.current_x - it3.pixel_width;
1979
1980
1981
1982 if (!it3.line_number_produced_p)
1983 {
1984 if (it3.lnum_pixel_width > 0)
1985 {
1986 top_x += it3.lnum_pixel_width;
1987 top_x_before_string += it3.lnum_pixel_width;
1988 }
1989 else if (it.line_number_produced_p)
1990 {
1991 top_x += it.lnum_pixel_width;
1992 top_x_before_string += it3.lnum_pixel_width;
1993 }
1994 }
1995
1996
1997
1998
1999
2000
2001 if (it3_moved
2002 && newline_in_string
2003 && IT_CHARPOS (it3) != charpos && EQ (it3.object, string))
2004 top_x = top_x_before_string;
2005 }
2006 }
2007
2008 *x = top_x;
2009
2010
2011
2012
2013 if (it.ascent == 0 && it.what == IT_IMAGE
2014 && it.method != GET_FROM_IMAGE
2015 && it.image_id < 0
2016 && it.max_ascent > 0)
2017 *y = max (top_y, window_top_y);
2018 else
2019 *y = max (top_y + max (0, it.max_ascent - it.ascent), window_top_y);
2020 *rtop = max (0, window_top_y - top_y);
2021 *rbot = max (0, bottom_y - it.last_visible_y);
2022 *rowh = max (0, (min (bottom_y, it.last_visible_y)
2023 - max (top_y, window_top_y)));
2024 *vpos = it.vpos;
2025 if (it.bidi_it.paragraph_dir == R2L)
2026 r2l = true;
2027 }
2028 }
2029 else
2030 {
2031
2032
2033
2034 struct it it2;
2035 void *it2data = NULL;
2036
2037 SAVE_IT (it2, it, it2data);
2038 if (IT_CHARPOS (it) < ZV && FETCH_BYTE (IT_BYTEPOS (it)) != '\n')
2039 move_it_by_lines (&it, 1);
2040 if (charpos < IT_CHARPOS (it)
2041 || (it.what == IT_EOB && charpos == IT_CHARPOS (it)))
2042 {
2043 visible_p = true;
2044 RESTORE_IT (&it2, &it2, it2data);
2045 move_it_to (&it2, charpos, -1, -1, -1, MOVE_TO_POS);
2046 *x = it2.current_x;
2047 if (it2.ascent == 0 && it2.what == IT_IMAGE
2048 && it2.method != GET_FROM_IMAGE
2049 && it2.image_id < 0
2050 && it2.max_ascent > 0)
2051 *y = it2.current_y;
2052 else
2053 *y = it2.current_y + it2.max_ascent - it2.ascent;
2054 *rtop = max (0, -it2.current_y);
2055 *rbot = max (0, ((it2.current_y + it2.max_ascent + it2.max_descent)
2056 - it.last_visible_y));
2057 *rowh = max (0, (min (it2.current_y + it2.max_ascent + it2.max_descent,
2058 it.last_visible_y)
2059 - max (max (it2.current_y,
2060 WINDOW_TAB_LINE_HEIGHT (w)),
2061 WINDOW_HEADER_LINE_HEIGHT (w))));
2062 *vpos = it2.vpos;
2063 if (it2.bidi_it.paragraph_dir == R2L)
2064 r2l = true;
2065 }
2066 else
2067 bidi_unshelve_cache (it2data, true);
2068 }
2069 bidi_unshelve_cache (itdata, false);
2070
2071 if (old_buffer)
2072 set_buffer_internal_1 (old_buffer);
2073
2074 if (visible_p)
2075 {
2076 if (w->hscroll > 0)
2077 *x -=
2078 window_hscroll_limited (w, WINDOW_XFRAME (w))
2079 * WINDOW_FRAME_COLUMN_WIDTH (w);
2080
2081
2082
2083
2084
2085 if (r2l)
2086 *x = window_box_width (w, TEXT_AREA) - *x - 1;
2087 }
2088
2089 #if false
2090
2091 if (visible_p)
2092 fprintf (stderr, "+pv pt=%d vs=%d --> x=%d y=%d rt=%d rb=%d rh=%d vp=%d\n",
2093 charpos, w->vscroll, *x, *y, *rtop, *rbot, *rowh, *vpos);
2094 else
2095 fprintf (stderr, "-pv pt=%d vs=%d\n", charpos, w->vscroll);
2096 #endif
2097
2098
2099 w->mode_line_height = prev_mode_line_height;
2100 w->header_line_height = prev_header_line_height;
2101 w->tab_line_height = prev_tab_line_height;
2102
2103 return visible_p;
2104 }
2105
2106
2107
2108
2109
2110
2111
2112 static int
2113 check_char_and_length (const unsigned char *str, int *len)
2114 {
2115 int c = string_char_and_length (str, len);
2116 if (!CHAR_VALID_P (c))
2117
2118
2119
2120 c = '?';
2121
2122 return c;
2123 }
2124
2125
2126
2127
2128
2129
2130 static struct text_pos
2131 string_pos_nchars_ahead (struct text_pos pos, Lisp_Object string, ptrdiff_t nchars)
2132 {
2133 eassert (STRINGP (string) && nchars >= 0);
2134
2135 if (STRING_MULTIBYTE (string))
2136 {
2137 const unsigned char *p = SDATA (string) + BYTEPOS (pos);
2138
2139 while (nchars--)
2140 {
2141 int len = BYTES_BY_CHAR_HEAD (*p);
2142 p += len;
2143 CHARPOS (pos) += 1;
2144 BYTEPOS (pos) += len;
2145 }
2146 }
2147 else
2148 SET_TEXT_POS (pos, CHARPOS (pos) + nchars, BYTEPOS (pos) + nchars);
2149
2150 return pos;
2151 }
2152
2153
2154
2155
2156
2157 static struct text_pos
2158 string_pos (ptrdiff_t charpos, Lisp_Object string)
2159 {
2160 struct text_pos pos;
2161 eassert (STRINGP (string));
2162 eassert (charpos >= 0);
2163 SET_TEXT_POS (pos, charpos, string_char_to_byte (string, charpos));
2164 return pos;
2165 }
2166
2167
2168
2169
2170
2171
2172 static struct text_pos
2173 c_string_pos (ptrdiff_t charpos, const char *s, bool multibyte_p)
2174 {
2175 struct text_pos pos;
2176
2177 eassert (s != NULL);
2178 eassert (charpos >= 0);
2179
2180 if (multibyte_p)
2181 {
2182 SET_TEXT_POS (pos, 0, 0);
2183 while (charpos--)
2184 {
2185 int len = BYTES_BY_CHAR_HEAD (*s);
2186 s += len;
2187 CHARPOS (pos) += 1;
2188 BYTEPOS (pos) += len;
2189 }
2190 }
2191 else
2192 SET_TEXT_POS (pos, charpos, charpos);
2193
2194 return pos;
2195 }
2196
2197
2198
2199
2200
2201 static ptrdiff_t
2202 number_of_chars (const char *s, bool multibyte_p)
2203 {
2204 ptrdiff_t nchars;
2205
2206 if (multibyte_p)
2207 {
2208 ptrdiff_t rest = strlen (s);
2209 const unsigned char *p = (const unsigned char *) s;
2210
2211 for (nchars = 0; rest > 0; ++nchars)
2212 {
2213 int len = BYTES_BY_CHAR_HEAD (*p);
2214 rest -= len, p += len;
2215 }
2216 }
2217 else
2218 nchars = strlen (s);
2219
2220 return nchars;
2221 }
2222
2223
2224
2225
2226
2227
2228 static void
2229 compute_string_pos (struct text_pos *newpos, struct text_pos pos, Lisp_Object string)
2230 {
2231 eassert (STRINGP (string));
2232 eassert (CHARPOS (*newpos) >= CHARPOS (pos));
2233
2234 if (STRING_MULTIBYTE (string))
2235 *newpos = string_pos_nchars_ahead (pos, string,
2236 CHARPOS (*newpos) - CHARPOS (pos));
2237 else
2238 BYTEPOS (*newpos) = CHARPOS (*newpos);
2239 }
2240
2241
2242
2243
2244
2245 int
2246 estimate_mode_line_height (struct frame *f, enum face_id face_id)
2247 {
2248 #ifdef HAVE_WINDOW_SYSTEM
2249 if (FRAME_WINDOW_P (f))
2250 {
2251 int height = FONT_HEIGHT (FRAME_FONT (f));
2252
2253
2254
2255 if (FRAME_FACE_CACHE (f))
2256 {
2257 struct face *face = FACE_FROM_ID_OR_NULL (f, face_id);
2258 if (face)
2259 {
2260 if (face->font)
2261 height = normal_char_height (face->font, -1);
2262 if (face->box_horizontal_line_width > 0)
2263 height += 2 * face->box_horizontal_line_width;
2264 }
2265 }
2266
2267 return height;
2268 }
2269 #endif
2270
2271 return 1;
2272 }
2273
2274
2275
2276
2277
2278
2279 void
2280 pixel_to_glyph_coords (struct frame *f, int pix_x, int pix_y, int *x, int *y,
2281 NativeRectangle *bounds, bool noclip)
2282 {
2283
2284 #ifdef HAVE_WINDOW_SYSTEM
2285 if (FRAME_WINDOW_P (f))
2286 {
2287
2288
2289 if (pix_x < 0)
2290 pix_x -= FRAME_COLUMN_WIDTH (f) - 1;
2291 if (pix_y < 0)
2292 pix_y -= FRAME_LINE_HEIGHT (f) - 1;
2293
2294 pix_x = FRAME_PIXEL_X_TO_COL (f, pix_x);
2295 pix_y = FRAME_PIXEL_Y_TO_LINE (f, pix_y);
2296
2297 if (bounds)
2298 STORE_NATIVE_RECT (*bounds,
2299 FRAME_COL_TO_PIXEL_X (f, pix_x),
2300 FRAME_LINE_TO_PIXEL_Y (f, pix_y),
2301 FRAME_COLUMN_WIDTH (f) - 1,
2302 FRAME_LINE_HEIGHT (f) - 1);
2303
2304
2305 if (!noclip)
2306 {
2307 if (pix_x < 0)
2308 pix_x = 0;
2309 else if (pix_x > FRAME_TOTAL_COLS (f))
2310 pix_x = FRAME_TOTAL_COLS (f);
2311
2312 if (pix_y < 0)
2313 pix_y = 0;
2314 else if (pix_y > FRAME_TOTAL_LINES (f))
2315 pix_y = FRAME_TOTAL_LINES (f);
2316 }
2317 }
2318 #endif
2319
2320 *x = pix_x;
2321 *y = pix_y;
2322 }
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333 struct glyph *
2334 x_y_to_hpos_vpos (struct window *w, int x, int y, int *hpos, int *vpos,
2335 int *dx, int *dy, int *area)
2336 {
2337 struct glyph *glyph, *end;
2338 struct glyph_row *row = NULL;
2339 int x0, i;
2340
2341
2342 for (i = 0; i < w->current_matrix->nrows; ++i)
2343 {
2344 row = MATRIX_ROW (w->current_matrix, i);
2345 if (!row->enabled_p)
2346 return NULL;
2347 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
2348 break;
2349 }
2350
2351 *vpos = i;
2352 *hpos = 0;
2353
2354
2355 if (i == w->current_matrix->nrows)
2356 return NULL;
2357
2358
2359 if (w->pseudo_window_p)
2360 {
2361 *area = TEXT_AREA;
2362 x0 = 0;
2363 }
2364 else
2365 {
2366 if (x < window_box_left_offset (w, TEXT_AREA))
2367 {
2368 *area = LEFT_MARGIN_AREA;
2369 x0 = window_box_left_offset (w, LEFT_MARGIN_AREA);
2370 }
2371 else if (x < window_box_right_offset (w, TEXT_AREA))
2372 {
2373 *area = TEXT_AREA;
2374 x0 = window_box_left_offset (w, TEXT_AREA) + min (row->x, 0);
2375 }
2376 else
2377 {
2378 *area = RIGHT_MARGIN_AREA;
2379 x0 = window_box_left_offset (w, RIGHT_MARGIN_AREA);
2380 }
2381 }
2382
2383
2384 glyph = row->glyphs[*area];
2385 end = glyph + row->used[*area];
2386 x -= x0;
2387 while (glyph < end && x >= glyph->pixel_width)
2388 {
2389 x -= glyph->pixel_width;
2390 ++glyph;
2391 }
2392
2393 if (glyph == end)
2394 return NULL;
2395
2396 if (dx)
2397 {
2398 *dx = x;
2399 *dy = y - (row->y + row->ascent - glyph->ascent);
2400 }
2401
2402 *hpos = glyph - row->glyphs[*area];
2403 return glyph;
2404 }
2405
2406
2407
2408
2409 static void
2410 frame_to_window_pixel_xy (struct window *w, int *x, int *y)
2411 {
2412 if (w->pseudo_window_p)
2413 {
2414
2415
2416 struct frame *f = XFRAME (w->frame);
2417 *x -= FRAME_INTERNAL_BORDER_WIDTH (f);
2418 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2419 }
2420 else
2421 {
2422 *x -= WINDOW_LEFT_EDGE_X (w);
2423 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
2424 }
2425 }
2426
2427 #ifdef HAVE_WINDOW_SYSTEM
2428
2429
2430
2431
2432
2433 int
2434 get_glyph_string_clip_rects (struct glyph_string *s, NativeRectangle *rects, int n)
2435 {
2436 Emacs_Rectangle r;
2437
2438 if (n <= 0)
2439 return 0;
2440
2441 if (s->row->full_width_p)
2442 {
2443
2444 r.x = WINDOW_LEFT_EDGE_X (s->w);
2445 if (s->row->mode_line_p)
2446 r.width = WINDOW_PIXEL_WIDTH (s->w) - WINDOW_RIGHT_DIVIDER_WIDTH (s->w);
2447 else
2448 r.width = WINDOW_PIXEL_WIDTH (s->w);
2449
2450
2451
2452 if (s->w->pseudo_window_p)
2453 r.height = s->row->visible_height;
2454 else
2455 r.height = s->height;
2456 }
2457 else
2458 {
2459
2460 r.x = window_box_left (s->w, s->area);
2461 r.width = window_box_width (s->w, s->area);
2462 r.height = s->row->visible_height;
2463 }
2464
2465 if (s->clip_head)
2466 if (r.x < s->clip_head->x)
2467 {
2468 if (r.width >= s->clip_head->x - r.x)
2469 r.width -= s->clip_head->x - r.x;
2470 else
2471 r.width = 0;
2472 r.x = s->clip_head->x;
2473 }
2474 if (s->clip_tail)
2475 if (r.x + r.width > s->clip_tail->x + s->clip_tail->background_width)
2476 {
2477 if (s->clip_tail->x + s->clip_tail->background_width >= r.x)
2478 r.width = s->clip_tail->x + s->clip_tail->background_width - r.x;
2479 else
2480 r.width = 0;
2481 }
2482
2483
2484
2485
2486 if (s->for_overlaps)
2487 {
2488 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2489 r.height = window_text_bottom_y (s->w) - r.y;
2490
2491
2492
2493
2494
2495
2496 if (s->for_overlaps & OVERLAPS_ERASED_CURSOR)
2497 {
2498 Emacs_Rectangle rc, r_save = r;
2499
2500 rc.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (s->w, s->w->phys_cursor.x);
2501 rc.y = s->w->phys_cursor.y;
2502 rc.width = s->w->phys_cursor_width;
2503 rc.height = s->w->phys_cursor_height;
2504
2505 gui_intersect_rectangles (&r_save, &rc, &r);
2506 }
2507 }
2508 else
2509 {
2510
2511
2512
2513 if (!s->row->full_width_p
2514 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2515 r.y = WINDOW_TAB_LINE_HEIGHT (s->w) + WINDOW_HEADER_LINE_HEIGHT (s->w);
2516 else
2517 r.y = max (0, s->row->y);
2518 }
2519
2520 r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y);
2521
2522
2523
2524 if (s->hl == DRAW_CURSOR)
2525 {
2526 struct glyph *glyph = s->first_glyph;
2527 int height, max_y;
2528
2529 if (s->x > r.x)
2530 {
2531 if (r.width >= s->x - r.x)
2532 r.width -= s->x - r.x;
2533 else
2534 r.width = 0;
2535 r.x = s->x;
2536 }
2537 r.width = min (r.width, glyph->pixel_width);
2538
2539
2540 height = min (glyph->ascent + glyph->descent,
2541 min (FRAME_LINE_HEIGHT (s->f), s->row->visible_height));
2542 max_y = window_text_bottom_y (s->w) - height;
2543 max_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, max_y);
2544 if (s->ybase - glyph->ascent > max_y)
2545 {
2546 r.y = max_y;
2547 r.height = height;
2548 }
2549 else
2550 {
2551
2552 height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent);
2553 if (height < r.height)
2554 {
2555 max_y = r.y + r.height;
2556 r.y = min (max_y, max (r.y, s->ybase + glyph->descent - height));
2557 r.height = min (max_y - r.y, height);
2558 }
2559 }
2560 }
2561
2562 if (s->row->clip)
2563 {
2564 Emacs_Rectangle r_save = r;
2565
2566 if (! gui_intersect_rectangles (&r_save, s->row->clip, &r))
2567 r.width = 0;
2568 }
2569
2570 if ((s->for_overlaps & OVERLAPS_BOTH) == 0
2571 || ((s->for_overlaps & OVERLAPS_BOTH) == OVERLAPS_BOTH && n == 1))
2572 {
2573 #ifdef CONVERT_FROM_EMACS_RECT
2574 CONVERT_FROM_EMACS_RECT (r, *rects);
2575 #else
2576 *rects = r;
2577 #endif
2578 return 1;
2579 }
2580 else
2581 {
2582
2583
2584
2585
2586 #ifdef CONVERT_FROM_EMACS_RECT
2587 Emacs_Rectangle rs[2];
2588 #else
2589 Emacs_Rectangle *rs = rects;
2590 #endif
2591 int i = 0, row_y = WINDOW_TO_FRAME_PIXEL_Y (s->w, s->row->y);
2592
2593 if (s->for_overlaps & OVERLAPS_PRED)
2594 {
2595 rs[i] = r;
2596 if (r.y + r.height > row_y)
2597 {
2598 if (r.y < row_y)
2599 rs[i].height = row_y - r.y;
2600 else
2601 rs[i].height = 0;
2602 }
2603 i++;
2604 }
2605 if (s->for_overlaps & OVERLAPS_SUCC)
2606 {
2607 rs[i] = r;
2608 if (r.y < row_y + s->row->visible_height)
2609 {
2610 if (r.y + r.height > row_y + s->row->visible_height)
2611 {
2612 rs[i].y = row_y + s->row->visible_height;
2613 rs[i].height = r.y + r.height - rs[i].y;
2614 }
2615 else
2616 rs[i].height = 0;
2617 }
2618 i++;
2619 }
2620
2621 n = i;
2622 #ifdef CONVERT_FROM_EMACS_RECT
2623 for (i = 0; i < n; i++)
2624 CONVERT_FROM_EMACS_RECT (rs[i], rects[i]);
2625 #endif
2626 return n;
2627 }
2628 }
2629
2630
2631
2632
2633 void
2634 get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2635 {
2636 get_glyph_string_clip_rects (s, nr, 1);
2637 }
2638
2639
2640
2641
2642
2643
2644
2645 void
2646 get_phys_cursor_geometry (struct window *w, struct glyph_row *row,
2647 struct glyph *glyph, int *xp, int *yp, int *heightp)
2648 {
2649 struct frame *f = XFRAME (WINDOW_FRAME (w));
2650 int x, y, wd, h, h0, y0, ascent;
2651
2652
2653
2654
2655
2656 wd = glyph->pixel_width;
2657
2658 x = w->phys_cursor.x;
2659 if (x < 0)
2660 {
2661 wd += x;
2662 x = 0;
2663 }
2664
2665 if (glyph->type == STRETCH_GLYPH
2666 && !x_stretch_cursor_p)
2667 wd = min (FRAME_COLUMN_WIDTH (f), wd);
2668 w->phys_cursor_width = wd;
2669
2670
2671
2672 y = w->phys_cursor.y;
2673 ascent = row->ascent;
2674
2675
2676
2677 if (!row->ends_at_zv_p && row->ascent < glyph->ascent)
2678 {
2679 y -= glyph->ascent - row->ascent;
2680 ascent = glyph->ascent;
2681 }
2682
2683
2684 h0 = min (FRAME_LINE_HEIGHT (f), row->visible_height);
2685
2686 h = max (h0, ascent + glyph->descent);
2687
2688
2689 h = min (h, row->height);
2690 h0 = min (h0, ascent + glyph->descent);
2691
2692 y0 = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
2693 if (y < y0)
2694 {
2695 h = max (h - (y0 - y) + 1, h0);
2696 y = y0 - 1;
2697 }
2698 else
2699 {
2700 y0 = window_text_bottom_y (w) - h0;
2701 if (y > y0)
2702 {
2703 h += y - y0;
2704 y = y0;
2705 }
2706 }
2707
2708 *xp = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
2709 *yp = WINDOW_TO_FRAME_PIXEL_Y (w, y);
2710 *heightp = h;
2711 }
2712
2713
2714
2715
2716
2717 void
2718 remember_mouse_glyph (struct frame *f, int gx, int gy, NativeRectangle *rect)
2719 {
2720 Lisp_Object window;
2721 struct window *w;
2722 struct glyph_row *r, *gr, *end_row;
2723 enum window_part part;
2724 enum glyph_row_area area;
2725 int x, y, width, height;
2726
2727 if (mouse_fine_grained_tracking)
2728 {
2729 STORE_NATIVE_RECT (*rect, gx, gy, 1, 1);
2730 return;
2731 }
2732
2733
2734
2735
2736 if (window_resize_pixelwise)
2737 {
2738 width = height = 1;
2739 goto virtual_glyph;
2740 }
2741 else if (!f->glyphs_initialized_p
2742 || (window = window_from_coordinates (f, gx, gy, &part, false, false),
2743 NILP (window)))
2744 {
2745 width = FRAME_SMALLEST_CHAR_WIDTH (f);
2746 height = FRAME_SMALLEST_FONT_HEIGHT (f);
2747 goto virtual_glyph;
2748 }
2749
2750 w = XWINDOW (window);
2751 width = WINDOW_FRAME_COLUMN_WIDTH (w);
2752 height = WINDOW_FRAME_LINE_HEIGHT (w);
2753
2754 x = window_relative_x_coord (w, part, gx);
2755 y = gy - WINDOW_TOP_EDGE_Y (w);
2756
2757 r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
2758 end_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
2759
2760 if (w->pseudo_window_p)
2761 {
2762 area = TEXT_AREA;
2763 part = ON_MODE_LINE;
2764 goto text_glyph;
2765 }
2766
2767 switch (part)
2768 {
2769 case ON_LEFT_MARGIN:
2770 area = LEFT_MARGIN_AREA;
2771 goto text_glyph;
2772
2773 case ON_RIGHT_MARGIN:
2774 area = RIGHT_MARGIN_AREA;
2775 goto text_glyph;
2776
2777 case ON_TAB_LINE:
2778 case ON_HEADER_LINE:
2779 case ON_MODE_LINE:
2780 gr = (part == ON_TAB_LINE
2781 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
2782 : (part == ON_HEADER_LINE
2783 ? MATRIX_HEADER_LINE_ROW (w->current_matrix)
2784 : MATRIX_MODE_LINE_ROW (w->current_matrix)));
2785 gy = gr->y;
2786 area = TEXT_AREA;
2787 goto text_glyph_row_found;
2788
2789 case ON_TEXT:
2790 area = TEXT_AREA;
2791
2792 text_glyph:
2793 gr = 0; gy = 0;
2794 for (; r <= end_row && r->enabled_p; ++r)
2795 if (r->y + r->height > y)
2796 {
2797 gr = r; gy = r->y;
2798 break;
2799 }
2800
2801 text_glyph_row_found:
2802 if (gr && gy <= y)
2803 {
2804 struct glyph *g = gr->glyphs[area];
2805 struct glyph *end = g + gr->used[area];
2806
2807 height = gr->height;
2808 for (gx = gr->x; g < end; gx += g->pixel_width, ++g)
2809 if (gx + g->pixel_width > x)
2810 break;
2811
2812 if (g < end)
2813 {
2814 if (g->type == IMAGE_GLYPH)
2815 {
2816
2817
2818 STORE_NATIVE_RECT (*rect, 0, 0, 0, 0);
2819 return;
2820 }
2821 width = g->pixel_width;
2822 }
2823 else
2824 {
2825
2826 x -= gx;
2827 gx += (x / width) * width;
2828 }
2829
2830 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2831 && part != ON_TAB_LINE)
2832 {
2833 gx += window_box_left_offset (w, area);
2834
2835
2836 height = min (height,
2837 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2838 }
2839 }
2840 else
2841 {
2842
2843 gx = (x / width) * width;
2844 y -= gy;
2845 gy += (y / height) * height;
2846 if (part != ON_MODE_LINE && part != ON_HEADER_LINE
2847 && part != ON_TAB_LINE)
2848
2849 height = min (height,
2850 max (0, WINDOW_BOX_HEIGHT_NO_MODE_LINE (w) - gy));
2851 }
2852 break;
2853
2854 case ON_LEFT_FRINGE:
2855 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2856 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2857 : window_box_right_offset (w, LEFT_MARGIN_AREA));
2858 width = WINDOW_LEFT_FRINGE_WIDTH (w);
2859 goto row_glyph;
2860
2861 case ON_RIGHT_FRINGE:
2862 gx = (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2863 ? window_box_right_offset (w, RIGHT_MARGIN_AREA)
2864 : window_box_right_offset (w, TEXT_AREA));
2865 if (WINDOW_RIGHT_DIVIDER_WIDTH (w) == 0
2866 && !WINDOW_HAS_VERTICAL_SCROLL_BAR (w)
2867 && !WINDOW_RIGHTMOST_P (w))
2868 if (gx < WINDOW_PIXEL_WIDTH (w) - width)
2869
2870
2871 width = WINDOW_RIGHT_FRINGE_WIDTH (w) - width;
2872 else
2873 width = WINDOW_PIXEL_WIDTH (w) - gx;
2874 else
2875 width = WINDOW_RIGHT_FRINGE_WIDTH (w);
2876
2877 goto row_glyph;
2878
2879 case ON_VERTICAL_BORDER:
2880 gx = WINDOW_PIXEL_WIDTH (w) - width;
2881 goto row_glyph;
2882
2883 case ON_VERTICAL_SCROLL_BAR:
2884 gx = (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)
2885 ? 0
2886 : (window_box_right_offset (w, RIGHT_MARGIN_AREA)
2887 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
2888 ? WINDOW_RIGHT_FRINGE_WIDTH (w)
2889 : 0)));
2890 width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
2891
2892 row_glyph:
2893 gr = 0, gy = 0;
2894 for (; r <= end_row && r->enabled_p; ++r)
2895 if (r->y + r->height > y)
2896 {
2897 gr = r; gy = r->y;
2898 break;
2899 }
2900
2901 if (gr && gy <= y)
2902 height = gr->height;
2903 else
2904 {
2905
2906 y -= gy;
2907 gy += (y / height) * height;
2908 }
2909 break;
2910
2911 case ON_RIGHT_DIVIDER:
2912 gx = WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
2913 width = WINDOW_RIGHT_DIVIDER_WIDTH (w);
2914 gy = 0;
2915
2916 height = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2917 goto add_edge;
2918
2919 case ON_BOTTOM_DIVIDER:
2920 gx = 0;
2921 width = WINDOW_PIXEL_WIDTH (w);
2922 gy = WINDOW_PIXEL_HEIGHT (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2923 height = WINDOW_BOTTOM_DIVIDER_WIDTH (w);
2924 goto add_edge;
2925
2926 default:
2927 ;
2928 virtual_glyph:
2929
2930
2931
2932
2933
2934
2935 if (gx < 0)
2936 gx -= width - 1;
2937 if (gy < 0)
2938 gy -= height - 1;
2939
2940 gx = (gx / width) * width;
2941 gy = (gy / height) * height;
2942
2943 goto store_rect;
2944 }
2945
2946 add_edge:
2947 gx += WINDOW_LEFT_EDGE_X (w);
2948 gy += WINDOW_TOP_EDGE_Y (w);
2949
2950 store_rect:
2951 STORE_NATIVE_RECT (*rect, gx, gy, width, height);
2952
2953
2954 #if false && defined HAVE_X_WINDOWS
2955 XDrawRectangle (FRAME_X_DISPLAY (f), FRAME_X_DRAWABLE (f),
2956 f->output_data.x->normal_gc,
2957 gx, gy, width, height);
2958 #endif
2959 }
2960
2961
2962 #endif
2963
2964 static void
2965 adjust_window_ends (struct window *w, struct glyph_row *row, bool current)
2966 {
2967 eassert (w);
2968 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
2969 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
2970 w->window_end_vpos
2971 = MATRIX_ROW_VPOS (row, current ? w->current_matrix : w->desired_matrix);
2972 }
2973
2974 static bool
2975 hscrolling_current_line_p (struct window *w)
2976 {
2977 return (!w->suspend_auto_hscroll
2978 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
2979 Qcurrent_line));
2980 }
2981
2982
2983
2984
2985
2986
2987
2988 static Lisp_Object
2989 safe_eval_handler (Lisp_Object arg, ptrdiff_t nargs, Lisp_Object *args)
2990 {
2991 add_to_log ("Error during redisplay: %S signaled %S",
2992 Flist (nargs, args), arg);
2993 return Qnil;
2994 }
2995
2996
2997
2998
2999
3000 static Lisp_Object
3001 safe__call (bool inhibit_quit, ptrdiff_t nargs, Lisp_Object func, va_list ap)
3002 {
3003 Lisp_Object val;
3004
3005 if (inhibit_eval_during_redisplay)
3006 val = Qnil;
3007 else
3008 {
3009 ptrdiff_t i;
3010 specpdl_ref count = SPECPDL_INDEX ();
3011 Lisp_Object *args;
3012 USE_SAFE_ALLOCA;
3013 SAFE_ALLOCA_LISP (args, nargs);
3014
3015 args[0] = func;
3016 for (i = 1; i < nargs; i++)
3017 args[i] = va_arg (ap, Lisp_Object);
3018
3019 specbind (Qinhibit_redisplay, Qt);
3020 if (inhibit_quit)
3021 specbind (Qinhibit_quit, Qt);
3022
3023
3024 val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
3025 safe_eval_handler);
3026 val = SAFE_FREE_UNBIND_TO (count, val);
3027 }
3028
3029 return val;
3030 }
3031
3032 Lisp_Object
3033 safe_call (ptrdiff_t nargs, Lisp_Object func, ...)
3034 {
3035 Lisp_Object retval;
3036 va_list ap;
3037
3038 va_start (ap, func);
3039 retval = safe__call (false, nargs, func, ap);
3040 va_end (ap);
3041 return retval;
3042 }
3043
3044
3045
3046
3047 Lisp_Object
3048 safe_call1 (Lisp_Object fn, Lisp_Object arg)
3049 {
3050 return safe_call (2, fn, arg);
3051 }
3052
3053 static Lisp_Object
3054 safe__call1 (bool inhibit_quit, Lisp_Object fn, ...)
3055 {
3056 Lisp_Object retval;
3057 va_list ap;
3058
3059 va_start (ap, fn);
3060 retval = safe__call (inhibit_quit, 2, fn, ap);
3061 va_end (ap);
3062 return retval;
3063 }
3064
3065 Lisp_Object
3066 safe_eval (Lisp_Object sexpr)
3067 {
3068 return safe__call1 (false, Qeval, sexpr);
3069 }
3070
3071 static Lisp_Object
3072 safe__eval (bool inhibit_quit, Lisp_Object sexpr)
3073 {
3074 return safe__call1 (inhibit_quit, Qeval, sexpr);
3075 }
3076
3077
3078
3079
3080 Lisp_Object
3081 safe_call2 (Lisp_Object fn, Lisp_Object arg1, Lisp_Object arg2)
3082 {
3083 return safe_call (3, fn, arg1, arg2);
3084 }
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095 static void
3096 CHECK_IT (struct it *it)
3097 {
3098 #if false
3099 if (it->method == GET_FROM_STRING)
3100 {
3101 eassert (STRINGP (it->string));
3102 eassert (IT_STRING_CHARPOS (*it) >= 0);
3103 }
3104 else
3105 {
3106 eassert (IT_STRING_CHARPOS (*it) < 0);
3107 if (it->method == GET_FROM_BUFFER)
3108 {
3109
3110 eassert (IT_CHARPOS (*it) == BYTE_TO_CHAR (IT_BYTEPOS (*it)));
3111 }
3112 }
3113
3114 if (it->dpvec)
3115 eassert (it->current.dpvec_index >= 0);
3116 else
3117 eassert (it->current.dpvec_index < 0);
3118 #endif
3119 }
3120
3121
3122
3123
3124
3125 static void
3126 CHECK_WINDOW_END (struct window *w)
3127 {
3128 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
3129 if (!MINI_WINDOW_P (w) && w->window_end_valid)
3130 {
3131 struct glyph_row *row;
3132 eassert ((row = MATRIX_ROW (w->current_matrix, w->window_end_vpos),
3133 !row->enabled_p
3134 || MATRIX_ROW_DISPLAYS_TEXT_P (row)
3135 || MATRIX_ROW_VPOS (row, w->current_matrix) == 0));
3136 }
3137 #endif
3138 }
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163 void
3164 init_iterator (struct it *it, struct window *w,
3165 ptrdiff_t charpos, ptrdiff_t bytepos,
3166 struct glyph_row *row, enum face_id base_face_id)
3167 {
3168 enum face_id remapped_base_face_id = base_face_id;
3169 int body_width = 0, body_height = 0;
3170
3171
3172 eassert (w != NULL && it != NULL);
3173 eassert (charpos < 0 || (charpos >= BUF_BEG (current_buffer)
3174 && charpos <= ZV));
3175
3176
3177
3178
3179
3180 if (!inhibit_free_realized_faces)
3181 {
3182 if (face_change)
3183 {
3184 face_change = false;
3185 XFRAME (w->frame)->face_change = 0;
3186 free_all_realized_faces (Qnil);
3187 }
3188 else if (XFRAME (w->frame)->face_change)
3189 {
3190 XFRAME (w->frame)->face_change = 0;
3191 free_all_realized_faces (w->frame);
3192 }
3193 }
3194
3195
3196 if (! NILP (Vface_remapping_alist))
3197 remapped_base_face_id
3198 = lookup_basic_face (w, XFRAME (w->frame), base_face_id);
3199
3200
3201
3202 if (row == NULL)
3203 {
3204 if (base_face_id == MODE_LINE_ACTIVE_FACE_ID
3205 || base_face_id == MODE_LINE_INACTIVE_FACE_ID)
3206 row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
3207 else if (base_face_id == TAB_LINE_FACE_ID)
3208 row = MATRIX_TAB_LINE_ROW (w->desired_matrix);
3209 else if (base_face_id == HEADER_LINE_FACE_ID)
3210 {
3211
3212 w->desired_matrix->tab_line_p = window_wants_tab_line (w);
3213 row = MATRIX_HEADER_LINE_ROW (w->desired_matrix);
3214 }
3215 }
3216
3217
3218
3219 memclear (it, sizeof *it);
3220 it->current.overlay_string_index = -1;
3221 it->current.dpvec_index = -1;
3222 it->base_face_id = remapped_base_face_id;
3223 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
3224 it->paragraph_embedding = L2R;
3225 it->bidi_it.w = w;
3226
3227
3228 XSETWINDOW (it->window, w);
3229 it->w = w;
3230 it->f = XFRAME (w->frame);
3231
3232 it->cmp_it.id = -1;
3233 it->cmp_it.parent_it = it;
3234
3235 if (max_redisplay_ticks > 0)
3236 update_redisplay_ticks (0, w);
3237
3238
3239 if (base_face_id == DEFAULT_FACE_ID
3240 && FRAME_WINDOW_P (it->f))
3241 {
3242 if (FIXNATP (BVAR (current_buffer, extra_line_spacing)))
3243 it->extra_line_spacing = XFIXNAT (BVAR (current_buffer, extra_line_spacing));
3244 else if (FLOATP (BVAR (current_buffer, extra_line_spacing)))
3245 it->extra_line_spacing = (XFLOAT_DATA (BVAR (current_buffer, extra_line_spacing))
3246 * FRAME_LINE_HEIGHT (it->f));
3247 else if (it->f->extra_line_spacing > 0)
3248 it->extra_line_spacing = it->f->extra_line_spacing;
3249 }
3250
3251
3252
3253
3254
3255 if (FRAME_FACE_CACHE (it->f) == NULL)
3256 init_frame_faces (it->f);
3257 if (FRAME_FACE_CACHE (it->f)->used == 0)
3258 recompute_basic_faces (it->f);
3259
3260 it->override_ascent = -1;
3261
3262
3263 it->ctl_arrow_p = !NILP (BVAR (current_buffer, ctl_arrow));
3264
3265
3266
3267
3268 it->selective = (FIXNUMP (BVAR (current_buffer, selective_display))
3269 ? (clip_to_bounds
3270 (-1, XFIXNUM (BVAR (current_buffer, selective_display)),
3271 PTRDIFF_MAX))
3272 : (!NILP (BVAR (current_buffer, selective_display))
3273 ? -1 : 0));
3274 it->selective_display_ellipsis_p
3275 = !NILP (BVAR (current_buffer, selective_display_ellipses));
3276
3277
3278 it->dp = window_display_table (w);
3279
3280
3281 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
3282
3283 it->tab_width = SANE_TAB_WIDTH (current_buffer);
3284
3285
3286 if (TRUNCATE != 0)
3287 it->line_wrap = TRUNCATE;
3288 if (base_face_id == DEFAULT_FACE_ID
3289 && !it->w->hscroll
3290 && (WINDOW_FULL_WIDTH_P (it->w)
3291 || NILP (Vtruncate_partial_width_windows)
3292 || (FIXNUMP (Vtruncate_partial_width_windows)
3293
3294 && (XFIXNUM (Vtruncate_partial_width_windows)
3295 <= WINDOW_TOTAL_COLS (it->w))))
3296 && NILP (BVAR (current_buffer, truncate_lines)))
3297 it->line_wrap = NILP (BVAR (current_buffer, word_wrap))
3298 ? WINDOW_WRAP : WORD_WRAP;
3299
3300
3301
3302
3303
3304
3305
3306 #ifdef HAVE_WINDOW_SYSTEM
3307 if (!(FRAME_WINDOW_P (it->f) && it->f->no_special_glyphs))
3308 #endif
3309 {
3310 if (it->line_wrap == TRUNCATE)
3311 {
3312
3313 eassert (it->glyph_row == NULL);
3314 produce_special_glyphs (it, IT_TRUNCATION);
3315 it->truncation_pixel_width = it->pixel_width;
3316 }
3317 else
3318 {
3319
3320 eassert (it->glyph_row == NULL);
3321 produce_special_glyphs (it, IT_CONTINUATION);
3322 it->continuation_pixel_width = it->pixel_width;
3323 }
3324 }
3325
3326
3327
3328 it->pixel_width = it->ascent = it->descent = 0;
3329 it->phys_ascent = it->phys_descent = 0;
3330
3331
3332
3333
3334 it->glyph_row = row;
3335 it->area = TEXT_AREA;
3336
3337
3338
3339
3340
3341 if (base_face_id != DEFAULT_FACE_ID)
3342 {
3343
3344 it->first_visible_x = 0;
3345 it->last_visible_x =
3346 WINDOW_PIXEL_WIDTH (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
3347 }
3348 else
3349 {
3350
3351
3352
3353
3354
3355
3356 if (hscrolling_current_line_p (w))
3357 {
3358 if (w->min_hscroll > 0)
3359 it->first_visible_x = w->min_hscroll * FRAME_COLUMN_WIDTH (it->f);
3360 else
3361 it->first_visible_x = 0;
3362 }
3363 else
3364 it->first_visible_x =
3365 window_hscroll_limited (w, it->f) * FRAME_COLUMN_WIDTH (it->f);
3366
3367 body_width = window_box_width (w, TEXT_AREA);
3368 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3369 && body_width != w->old_body_pixel_width)
3370 FRAME_WINDOW_CHANGE (it->f) = true;
3371 it->last_visible_x = it->first_visible_x + body_width;
3372
3373
3374
3375
3376 if (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
3377 {
3378 if (it->line_wrap == TRUNCATE)
3379 it->last_visible_x -= it->truncation_pixel_width;
3380 else
3381 it->last_visible_x -= it->continuation_pixel_width;
3382 }
3383
3384 it->tab_line_p = window_wants_tab_line (w);
3385 it->header_line_p = window_wants_header_line (w);
3386 body_height = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
3387 it->current_y = body_height + w->vscroll;
3388 }
3389
3390
3391 if (!FRAME_WINDOW_P (it->f)
3392 && !WINDOW_RIGHTMOST_P (it->w))
3393 it->last_visible_x -= 1;
3394
3395 it->last_visible_y = window_text_bottom_y (w);
3396 body_height += it->last_visible_y;
3397 if (!w->pseudo_window_p && !MINI_WINDOW_P (w)
3398 && body_height != w->old_body_pixel_height)
3399 FRAME_WINDOW_CHANGE (it->f) = true;
3400
3401
3402
3403 if (base_face_id != DEFAULT_FACE_ID)
3404 {
3405 struct face *face;
3406
3407 it->face_id = remapped_base_face_id;
3408
3409
3410
3411 face = FACE_FROM_ID_OR_NULL (it->f, remapped_base_face_id);
3412 if (face && face->box != FACE_NO_BOX)
3413 {
3414 int box_thickness = face->box_vertical_line_width;
3415 it->face_box_p = true;
3416 it->start_of_box_run_p = true;
3417
3418
3419 if (box_thickness > 0)
3420 it->last_visible_x -= box_thickness;
3421 }
3422 }
3423
3424
3425
3426 if (charpos >= BUF_BEG (current_buffer))
3427 {
3428 it->stop_charpos = charpos;
3429 it->end_charpos = ZV;
3430 eassert (charpos == BYTE_TO_CHAR (bytepos));
3431 IT_CHARPOS (*it) = charpos;
3432 IT_BYTEPOS (*it) = bytepos;
3433
3434
3435
3436 it->face_id = it->base_face_id;
3437
3438 it->start = it->current;
3439
3440
3441
3442
3443
3444
3445
3446 it->bidi_p =
3447 !redisplay__inhibit_bidi
3448 && !NILP (BVAR (current_buffer, bidi_display_reordering))
3449 && it->multibyte_p;
3450
3451
3452
3453 if (it->bidi_p)
3454 {
3455
3456
3457
3458
3459 if (base_face_id == DEFAULT_FACE_ID
3460 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
3461 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
3462 {
3463 if (it->line_wrap == TRUNCATE)
3464 it->last_visible_x -= it->truncation_pixel_width;
3465 else
3466 it->last_visible_x -= it->continuation_pixel_width;
3467 }
3468
3469
3470 if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3471 Qleft_to_right))
3472 it->paragraph_embedding = L2R;
3473 else if (EQ (BVAR (current_buffer, bidi_paragraph_direction),
3474 Qright_to_left))
3475 it->paragraph_embedding = R2L;
3476 else
3477 it->paragraph_embedding = NEUTRAL_DIR;
3478 bidi_unshelve_cache (NULL, false);
3479 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
3480 &it->bidi_it);
3481 }
3482
3483
3484
3485 it->medium_narrowing_begv = 0;
3486
3487
3488 reseat (it, it->current.pos, true);
3489 }
3490
3491 CHECK_IT (it);
3492 }
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580 static int
3581 get_narrowed_width (struct window *w)
3582 {
3583
3584
3585 int fact = FRAME_WINDOW_P (XFRAME (w->frame)) ? 3 : 2;
3586
3587
3588
3589 int width = window_body_width (w, WINDOW_BODY_IN_CANONICAL_CHARS)
3590 - ((WINDOW_RIGHT_FRINGE_WIDTH (w) == 0
3591 || WINDOW_LEFT_FRINGE_WIDTH (w) == 0) ? 1 : 0);
3592 return fact * max (1, width);
3593 }
3594
3595 static int
3596 get_narrowed_len (struct window *w)
3597 {
3598 int height = window_body_height (w, WINDOW_BODY_IN_CANONICAL_CHARS);
3599 return get_narrowed_width (w) * max (1, height);
3600 }
3601
3602 static ptrdiff_t
3603 get_medium_narrowing_begv (struct window *w, ptrdiff_t pos)
3604 {
3605 int len = get_narrowed_len (w);
3606 return max ((pos / len - 1) * len, BEGV);
3607 }
3608
3609 static ptrdiff_t
3610 get_medium_narrowing_zv (struct window *w, ptrdiff_t pos)
3611 {
3612 int len = get_narrowed_len (w);
3613 return min ((pos / len + 1) * len, ZV);
3614 }
3615
3616
3617
3618
3619
3620
3621 static ptrdiff_t
3622 get_nearby_bol_pos (ptrdiff_t pos)
3623 {
3624 ptrdiff_t start, pos_bytepos, cur, next, found, bol = BEGV - 1, init_pos = pos;
3625 int dist;
3626 for (dist = 500; dist <= 500000; dist *= 10)
3627 {
3628 pos_bytepos = pos == BEGV ? BEGV_BYTE : CHAR_TO_BYTE (pos);
3629 start = pos - dist < BEGV ? BEGV : pos - dist;
3630 for (cur = start; cur < pos; cur = next)
3631 {
3632 next = find_newline1 (cur, CHAR_TO_BYTE (cur),
3633 pos, pos_bytepos,
3634 1, &found, NULL, false);
3635 if (found)
3636 bol = next;
3637 else
3638 break;
3639 }
3640 if (bol >= BEGV || start == BEGV)
3641 break;
3642 else
3643 pos = pos - dist < BEGV ? BEGV : pos - dist;
3644 }
3645 eassert (bol <= init_pos);
3646 return bol;
3647 }
3648
3649 ptrdiff_t
3650 get_small_narrowing_begv (struct window *w, ptrdiff_t pos)
3651 {
3652 int len = get_narrowed_width (w);
3653 ptrdiff_t bol_pos = max (get_nearby_bol_pos (pos), BEGV);
3654 return max (bol_pos + ((pos - bol_pos) / len - 1) * len, BEGV);
3655 }
3656
3657 ptrdiff_t
3658 get_large_narrowing_begv (ptrdiff_t pos)
3659 {
3660 if (long_line_optimizations_region_size <= 0)
3661 return BEGV;
3662 int len = long_line_optimizations_region_size / 2;
3663 int begv = max (pos - len, BEGV);
3664 int limit = long_line_optimizations_bol_search_limit;
3665 while (limit > 0)
3666 {
3667 if (begv == BEGV || FETCH_BYTE (CHAR_TO_BYTE (begv) - 1) == '\n')
3668 return begv;
3669 begv--;
3670 limit--;
3671 }
3672 return begv;
3673 }
3674
3675 ptrdiff_t
3676 get_large_narrowing_zv (ptrdiff_t pos)
3677 {
3678 if (long_line_optimizations_region_size <= 0)
3679 return ZV;
3680 int len = long_line_optimizations_region_size / 2;
3681 return min (pos + len, ZV);
3682 }
3683
3684 static void
3685 unwind_narrowed_begv (Lisp_Object point_min)
3686 {
3687 SET_BUF_BEGV (current_buffer, XFIXNUM (point_min));
3688 }
3689
3690
3691
3692
3693 #define SET_WITH_NARROWED_BEGV(IT,DST,EXPR,BV) \
3694 do { \
3695 if (IT->medium_narrowing_begv) \
3696 { \
3697 specpdl_ref count = SPECPDL_INDEX (); \
3698 record_unwind_protect (unwind_narrowed_begv, Fpoint_min ()); \
3699 SET_BUF_BEGV (current_buffer, BV); \
3700 DST = EXPR; \
3701 unbind_to (count, Qnil); \
3702 } \
3703 else \
3704 DST = EXPR; \
3705 } while (0)
3706
3707
3708
3709 void
3710 start_display (struct it *it, struct window *w, struct text_pos pos)
3711 {
3712 struct glyph_row *row;
3713 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
3714
3715 row = w->desired_matrix->rows + first_vpos;
3716 init_iterator (it, w, CHARPOS (pos), BYTEPOS (pos), row, DEFAULT_FACE_ID);
3717 it->first_vpos = first_vpos;
3718
3719
3720
3721 if (it->method == GET_FROM_BUFFER && it->line_wrap != TRUNCATE)
3722 {
3723 int first_y = it->current_y;
3724
3725
3726
3727 bool start_at_line_beg_p = (CHARPOS (pos) == BEGV
3728 || FETCH_BYTE (BYTEPOS (pos) - 1) == '\n');
3729 if (!start_at_line_beg_p)
3730 {
3731 int new_x;
3732
3733 reseat_at_previous_visible_line_start (it);
3734 move_it_to (it, CHARPOS (pos), -1, -1, -1, MOVE_TO_POS);
3735
3736 new_x = it->current_x + it->pixel_width;
3737
3738
3739
3740
3741
3742
3743
3744 if (it->current_x > 0
3745 && it->line_wrap != TRUNCATE
3746 && (
3747 new_x > it->last_visible_x
3748
3749
3750 || (new_x == it->last_visible_x
3751 && FRAME_WINDOW_P (it->f)
3752 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
3753 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
3754 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
3755 {
3756 if ((it->current.dpvec_index >= 0
3757 || it->current.overlay_string_index >= 0)
3758
3759
3760
3761
3762
3763 && it->c != '\n')
3764 {
3765 set_iterator_to_next (it, true);
3766 move_it_in_display_line_to (it, -1, -1, 0);
3767 }
3768
3769 it->continuation_lines_width += it->current_x;
3770 }
3771
3772
3773
3774
3775
3776 else if (it->current.dpvec_index >= 0)
3777 it->current.dpvec_index = 0;
3778
3779
3780
3781
3782 it->max_ascent = it->max_descent = 0;
3783 it->max_phys_ascent = it->max_phys_descent = 0;
3784
3785 it->current_y = first_y;
3786 it->vpos = 0;
3787 it->current_x = it->hpos = 0;
3788 }
3789 }
3790 }
3791
3792
3793
3794
3795
3796 static bool
3797 in_ellipses_for_invisible_text_p (struct display_pos *pos, struct window *w)
3798 {
3799 Lisp_Object prop, window;
3800 bool ellipses_p = false;
3801 ptrdiff_t charpos = CHARPOS (pos->pos);
3802
3803
3804
3805
3806
3807 if (pos->dpvec_index >= 0
3808 && pos->overlay_string_index < 0
3809 && CHARPOS (pos->string_pos) < 0
3810 && charpos > BEGV
3811 && (XSETWINDOW (window, w),
3812 prop = Fget_char_property (make_fixnum (charpos),
3813 Qinvisible, window),
3814 TEXT_PROP_MEANS_INVISIBLE (prop) == 0))
3815 {
3816 prop = Fget_char_property (make_fixnum (charpos - 1), Qinvisible,
3817 window);
3818 ellipses_p = 2 == TEXT_PROP_MEANS_INVISIBLE (prop);
3819 }
3820
3821 return ellipses_p;
3822 }
3823
3824
3825
3826
3827
3828
3829
3830 static bool
3831 init_from_display_pos (struct it *it, struct window *w, struct display_pos *pos)
3832 {
3833 ptrdiff_t charpos = CHARPOS (pos->pos), bytepos = BYTEPOS (pos->pos);
3834 int i;
3835 bool overlay_strings_with_newlines = false;
3836
3837
3838
3839
3840
3841 if (in_ellipses_for_invisible_text_p (pos, w))
3842 {
3843 --charpos;
3844 bytepos = 0;
3845 }
3846
3847
3848
3849
3850
3851
3852
3853
3854
3855
3856 init_iterator (it, w, charpos, bytepos, NULL, DEFAULT_FACE_ID);
3857
3858
3859
3860
3861 for (i = 0; i < it->n_overlay_strings && i < OVERLAY_STRING_CHUNK_SIZE; ++i)
3862 {
3863 const char *s = SSDATA (it->overlay_strings[i]);
3864 const char *e = s + SBYTES (it->overlay_strings[i]);
3865
3866 while (s < e && *s != '\n')
3867 ++s;
3868
3869 if (s < e)
3870 {
3871 overlay_strings_with_newlines = true;
3872 break;
3873 }
3874 }
3875
3876
3877
3878 if (pos->overlay_string_index >= 0)
3879 {
3880 int relative_index;
3881
3882
3883
3884
3885
3886 if (it->method == GET_FROM_IMAGE)
3887 pop_it (it);
3888
3889
3890
3891
3892 if (pos->overlay_string_index >= OVERLAY_STRING_CHUNK_SIZE)
3893 {
3894 ptrdiff_t n = pos->overlay_string_index / OVERLAY_STRING_CHUNK_SIZE;
3895 it->current.overlay_string_index = 0;
3896 while (n--)
3897 {
3898 load_overlay_strings (it, 0);
3899 it->current.overlay_string_index += OVERLAY_STRING_CHUNK_SIZE;
3900 }
3901 }
3902
3903 it->current.overlay_string_index = pos->overlay_string_index;
3904 relative_index = (it->current.overlay_string_index
3905 % OVERLAY_STRING_CHUNK_SIZE);
3906 it->string = it->overlay_strings[relative_index];
3907 eassert (STRINGP (it->string));
3908 it->current.string_pos = pos->string_pos;
3909 it->method = GET_FROM_STRING;
3910 it->end_charpos = SCHARS (it->string);
3911
3912 if (it->bidi_p)
3913 {
3914 it->bidi_it.string.lstring = it->string;
3915 it->bidi_it.string.s = NULL;
3916 it->bidi_it.string.schars = SCHARS (it->string);
3917 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
3918 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
3919 it->bidi_it.string.unibyte = !it->multibyte_p;
3920 it->bidi_it.w = it->w;
3921 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3922 FRAME_WINDOW_P (it->f), &it->bidi_it);
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932 if (CHARPOS (pos->string_pos) == 0)
3933 {
3934 get_visually_first_element (it);
3935 if (IT_STRING_CHARPOS (*it) != 0)
3936 do {
3937
3938 eassert (it->bidi_it.charpos < it->bidi_it.string.schars);
3939 bidi_move_to_visually_next (&it->bidi_it);
3940 } while (it->bidi_it.charpos != 0);
3941 }
3942 eassert (IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
3943 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos);
3944 }
3945 }
3946
3947 if (CHARPOS (pos->string_pos) >= 0)
3948 {
3949
3950
3951
3952 it->current.string_pos = pos->string_pos;
3953 eassert (STRINGP (it->string));
3954 if (it->bidi_p)
3955 bidi_init_it (IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it),
3956 FRAME_WINDOW_P (it->f), &it->bidi_it);
3957 }
3958
3959
3960
3961 if (pos->dpvec_index >= 0)
3962 {
3963 if (it->dpvec == NULL)
3964 get_next_display_element (it);
3965 eassert (it->dpvec && it->current.dpvec_index == 0);
3966 it->current.dpvec_index = pos->dpvec_index;
3967 }
3968
3969 CHECK_IT (it);
3970 return !overlay_strings_with_newlines;
3971 }
3972
3973
3974
3975
3976
3977 static void
3978 init_to_row_start (struct it *it, struct window *w, struct glyph_row *row)
3979 {
3980 init_from_display_pos (it, w, &row->start);
3981 it->start = row->start;
3982 it->continuation_lines_width = row->continuation_lines_width;
3983 CHECK_IT (it);
3984 }
3985
3986
3987
3988
3989
3990
3991
3992
3993 static bool
3994 init_to_row_end (struct it *it, struct window *w, struct glyph_row *row)
3995 {
3996 bool success = false;
3997
3998 if (init_from_display_pos (it, w, &row->end))
3999 {
4000 if (row->continued_p)
4001 it->continuation_lines_width
4002 = row->continuation_lines_width + row->pixel_width;
4003 CHECK_IT (it);
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013 if (get_next_display_element (it)
4014 && (it->bidi_it.scan_dir == -1 && it->cmp_it.id >= 0))
4015 success = false;
4016 else
4017 success = true;
4018 }
4019
4020 return success;
4021 }
4022
4023
4024
4025
4026
4027
4028
4029
4030
4031
4032
4033
4034 static void
4035 handle_stop (struct it *it)
4036 {
4037 enum prop_handled handled;
4038 bool handle_overlay_change_p;
4039 struct props *p;
4040
4041 it->dpvec = NULL;
4042 it->current.dpvec_index = -1;
4043 handle_overlay_change_p = !it->ignore_overlay_strings_at_pos_p;
4044 it->ellipsis_p = false;
4045
4046
4047 if (it->selective_display_ellipsis_p)
4048 it->saved_face_id = it->face_id;
4049
4050
4051
4052
4053
4054
4055
4056
4057
4058
4059
4060
4061
4062
4063
4064
4065
4066
4067
4068
4069
4070
4071
4072
4073
4074
4075
4076
4077
4078
4079
4080
4081
4082
4083
4084
4085
4086
4087
4088
4089
4090
4091
4092 do
4093 {
4094 handled = HANDLED_NORMALLY;
4095
4096
4097 for (p = it_props; p->handler; ++p)
4098 {
4099 handled = p->handler (it);
4100
4101 if (handled == HANDLED_RECOMPUTE_PROPS)
4102 break;
4103 else if (handled == HANDLED_RETURN)
4104 {
4105
4106
4107 if (!handle_overlay_change_p
4108 || it->sp > 1
4109
4110
4111
4112
4113
4114
4115 || (it->current.overlay_string_index < 0
4116 && !get_overlay_strings_1 (it, 0, false)))
4117 {
4118 if (it->ellipsis_p)
4119 setup_for_ellipsis (it, 0);
4120
4121
4122
4123
4124
4125 if (STRINGP (it->string) && !SCHARS (it->string))
4126 pop_it (it);
4127 return;
4128 }
4129 else if (STRINGP (it->string) && !SCHARS (it->string))
4130 pop_it (it);
4131 else
4132 {
4133 it->string_from_display_prop_p = false;
4134 it->from_disp_prop_p = false;
4135 handle_overlay_change_p = false;
4136 }
4137 handled = HANDLED_RECOMPUTE_PROPS;
4138 break;
4139 }
4140 else if (handled == HANDLED_OVERLAY_STRING_CONSUMED)
4141 handle_overlay_change_p = false;
4142 }
4143
4144 if (handled != HANDLED_RECOMPUTE_PROPS)
4145 {
4146
4147
4148 if (it->method == GET_FROM_DISPLAY_VECTOR)
4149 handle_overlay_change_p = false;
4150
4151
4152
4153
4154 if (handle_overlay_change_p)
4155 handled = handle_overlay_change (it);
4156 }
4157
4158 if (it->ellipsis_p)
4159 {
4160 setup_for_ellipsis (it, 0);
4161 break;
4162 }
4163 }
4164 while (handled == HANDLED_RECOMPUTE_PROPS);
4165
4166
4167 if (handled == HANDLED_NORMALLY)
4168 compute_stop_pos (it);
4169 }
4170
4171
4172
4173
4174
4175 static void
4176 compute_stop_pos (struct it *it)
4177 {
4178 register INTERVAL iv, next_iv;
4179 Lisp_Object object, limit, position;
4180 ptrdiff_t charpos, bytepos;
4181
4182 if (STRINGP (it->string))
4183 {
4184
4185
4186 it->stop_charpos = it->end_charpos;
4187 object = it->string;
4188 limit = Qnil;
4189 charpos = IT_STRING_CHARPOS (*it);
4190 bytepos = IT_STRING_BYTEPOS (*it);
4191 }
4192 else
4193 {
4194 ptrdiff_t pos;
4195
4196
4197
4198 if (it->end_charpos > ZV)
4199 it->end_charpos = ZV;
4200 it->stop_charpos = it->end_charpos;
4201
4202
4203
4204
4205
4206 charpos = IT_CHARPOS (*it);
4207 bytepos = IT_BYTEPOS (*it);
4208 pos = next_overlay_change (charpos);
4209 if (pos < it->stop_charpos)
4210 it->stop_charpos = pos;
4211
4212 if (!NILP (BVAR (current_buffer, enable_multibyte_characters))
4213 && !NILP (Vauto_composition_mode)
4214 && composition_break_at_point
4215 && charpos < PT && PT < it->stop_charpos)
4216 it->stop_charpos = PT;
4217
4218
4219
4220 XSETBUFFER (object, current_buffer);
4221 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4222
4223
4224
4225
4226
4227
4228 if (!composition_break_at_point
4229 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
4230 && !NILP (Vauto_composition_mode))
4231 {
4232 ptrdiff_t endpos = charpos + 10 * TEXT_PROP_DISTANCE_LIMIT;
4233 bool found = false;
4234
4235 if (pos > ZV)
4236 pos = ZV;
4237 if (endpos > ZV)
4238 endpos = ZV;
4239 ptrdiff_t bpos = CHAR_TO_BYTE (pos);
4240 while (pos < endpos)
4241 {
4242 int ch = fetch_char_advance_no_check (&pos, &bpos);
4243 if (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\f')
4244 {
4245 found = true;
4246 break;
4247 }
4248 }
4249 if (found)
4250 pos--;
4251 else if (it->stop_charpos < endpos)
4252 pos = it->stop_charpos;
4253 else
4254 {
4255
4256 pos = charpos + TEXT_PROP_DISTANCE_LIMIT;
4257 }
4258 }
4259 limit = make_fixnum (pos);
4260 }
4261
4262
4263
4264 position = make_fixnum (charpos);
4265 iv = validate_interval_range (object, &position, &position, false);
4266 if (iv)
4267 {
4268 Lisp_Object values_here[LAST_PROP_IDX];
4269 struct props *p;
4270
4271
4272 for (p = it_props; p->handler; ++p)
4273 values_here[p->idx] = textget (iv->plist,
4274 builtin_lisp_symbol (p->name));
4275
4276
4277
4278 for (next_iv = next_interval (iv);
4279 (next_iv
4280 && (NILP (limit)
4281 || XFIXNAT (limit) > next_iv->position));
4282 next_iv = next_interval (next_iv))
4283 {
4284 for (p = it_props; p->handler; ++p)
4285 {
4286 Lisp_Object new_value = textget (next_iv->plist,
4287 builtin_lisp_symbol (p->name));
4288 if (!EQ (values_here[p->idx], new_value))
4289 break;
4290 }
4291
4292 if (p->handler)
4293 break;
4294 }
4295
4296 if (next_iv)
4297 {
4298 if (FIXNUMP (limit)
4299 && next_iv->position >= XFIXNAT (limit))
4300
4301 it->stop_charpos = min (XFIXNAT (limit), it->stop_charpos);
4302 else
4303
4304 it->stop_charpos = min (it->stop_charpos, next_iv->position);
4305 }
4306 }
4307
4308 if (it->cmp_it.id < 0)
4309 {
4310 ptrdiff_t stoppos = it->end_charpos;
4311
4312 if (it->bidi_p && it->bidi_it.scan_dir < 0)
4313 stoppos = -1;
4314 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos,
4315 stoppos, it->string);
4316 }
4317
4318 eassert (STRINGP (it->string)
4319 || (it->stop_charpos >= BEGV
4320 && it->stop_charpos >= IT_CHARPOS (*it)));
4321 }
4322
4323
4324
4325
4326 #define MAX_DISP_SCAN 250
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340 ptrdiff_t
4341 compute_display_string_pos (struct text_pos *position,
4342 struct bidi_string_data *string,
4343 struct window *w,
4344 bool frame_window_p, int *disp_prop)
4345 {
4346
4347 Lisp_Object object, object1;
4348 Lisp_Object pos, spec, limpos;
4349 bool string_p = string && (STRINGP (string->lstring) || string->s);
4350 ptrdiff_t eob = string_p ? string->schars : ZV;
4351 ptrdiff_t begb = string_p ? 0 : BEGV;
4352 ptrdiff_t bufpos, charpos = CHARPOS (*position);
4353 ptrdiff_t lim =
4354 (charpos < eob - MAX_DISP_SCAN) ? charpos + MAX_DISP_SCAN : eob;
4355 struct text_pos tpos;
4356 int rv = 0;
4357
4358 if (string && STRINGP (string->lstring))
4359 object1 = object = string->lstring;
4360 else if (w && !string_p)
4361 {
4362 XSETWINDOW (object, w);
4363 object1 = Qnil;
4364 }
4365 else
4366 object1 = object = Qnil;
4367
4368 *disp_prop = 1;
4369
4370 if (charpos >= eob
4371
4372
4373 || string->from_disp_str
4374
4375 || (string->s && !STRINGP (object)))
4376 {
4377 *disp_prop = 0;
4378 return eob;
4379 }
4380
4381
4382
4383 pos = make_fixnum (charpos);
4384 if (STRINGP (object))
4385 bufpos = string->bufpos;
4386 else
4387 bufpos = charpos;
4388 tpos = *position;
4389 if (!NILP (spec = Fget_char_property (pos, Qdisplay, object))
4390 && (charpos <= begb
4391 || !EQ (Fget_char_property (make_fixnum (charpos - 1), Qdisplay,
4392 object),
4393 spec))
4394 && (rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos, bufpos,
4395 frame_window_p)))
4396 {
4397 if (rv == 2)
4398 *disp_prop = 2;
4399 return charpos;
4400 }
4401
4402
4403
4404 limpos = make_fixnum (lim);
4405 do {
4406 pos = Fnext_single_char_property_change (pos, Qdisplay, object1, limpos);
4407 CHARPOS (tpos) = XFIXNAT (pos);
4408 if (CHARPOS (tpos) >= lim)
4409 {
4410 *disp_prop = 0;
4411 break;
4412 }
4413 if (STRINGP (object))
4414 BYTEPOS (tpos) = string_char_to_byte (object, CHARPOS (tpos));
4415 else
4416 BYTEPOS (tpos) = CHAR_TO_BYTE (CHARPOS (tpos));
4417 spec = Fget_char_property (pos, Qdisplay, object);
4418 if (!STRINGP (object))
4419 bufpos = CHARPOS (tpos);
4420 } while (NILP (spec)
4421 || !(rv = handle_display_spec (NULL, spec, object1, Qnil, &tpos,
4422 bufpos, frame_window_p)));
4423 if (rv == 2)
4424 *disp_prop = 2;
4425
4426 return CHARPOS (tpos);
4427 }
4428
4429
4430
4431
4432
4433
4434 ptrdiff_t
4435 compute_display_string_end (ptrdiff_t charpos, struct bidi_string_data *string)
4436 {
4437
4438 Lisp_Object object =
4439 (string && STRINGP (string->lstring)) ? string->lstring : Qnil;
4440 Lisp_Object pos = make_fixnum (charpos);
4441 ptrdiff_t eob =
4442 (STRINGP (object) || (string && string->s)) ? string->schars : ZV;
4443
4444 if (charpos >= eob || (string->s && !STRINGP (object)))
4445 return eob;
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461 if (NILP (Fget_char_property (pos, Qdisplay, object)))
4462 return -1;
4463
4464
4465
4466 pos = Fnext_single_char_property_change (pos, Qdisplay, object, Qnil);
4467
4468 return XFIXNAT (pos);
4469 }
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481 static enum prop_handled
4482 handle_fontified_prop (struct it *it)
4483 {
4484 Lisp_Object prop, pos;
4485 enum prop_handled handled = HANDLED_NORMALLY;
4486
4487 if (!NILP (Vmemory_full))
4488 return handled;
4489
4490
4491
4492
4493
4494 if (!STRINGP (it->string)
4495 && it->s == NULL
4496 && !NILP (Vfontification_functions)
4497 && !(input_was_pending && redisplay_skip_fontification_on_input)
4498 && !NILP (Vrun_hooks)
4499 && (pos = make_fixnum (IT_CHARPOS (*it)),
4500 prop = Fget_char_property (pos, Qfontified, Qnil),
4501
4502
4503 NILP (prop) && IT_CHARPOS (*it) < Z))
4504 {
4505 specpdl_ref count = SPECPDL_INDEX ();
4506 Lisp_Object val;
4507 struct buffer *obuf = current_buffer;
4508 ptrdiff_t begv = BEGV, zv = ZV;
4509 bool old_clip_changed = current_buffer->clip_changed;
4510 bool saved_inhibit_flag = it->f->inhibit_clear_image_cache;
4511
4512 val = Vfontification_functions;
4513 specbind (Qfontification_functions, Qnil);
4514
4515 eassert (it->end_charpos == ZV);
4516
4517 if (current_buffer->long_line_optimizations_p
4518 && long_line_optimizations_region_size > 0)
4519 {
4520 ptrdiff_t begv = it->large_narrowing_begv;
4521 ptrdiff_t zv = it->large_narrowing_zv;
4522 ptrdiff_t charpos = IT_CHARPOS (*it);
4523 if (charpos < begv || charpos > zv)
4524 {
4525 begv = get_large_narrowing_begv (charpos);
4526 zv = get_large_narrowing_zv (charpos);
4527 }
4528 if (begv != BEG || zv != Z)
4529 labeled_narrow_to_region (make_fixnum (begv), make_fixnum (zv),
4530 Qlong_line_optimizations_in_fontification_functions);
4531 }
4532
4533
4534
4535 it->f->inhibit_clear_image_cache = true;
4536
4537 if (!CONSP (val) || EQ (XCAR (val), Qlambda))
4538 safe_call1 (val, pos);
4539 else
4540 {
4541 Lisp_Object fns, fn;
4542
4543 fns = Qnil;
4544
4545 for (; CONSP (val); val = XCDR (val))
4546 {
4547 fn = XCAR (val);
4548
4549 if (EQ (fn, Qt))
4550 {
4551
4552
4553
4554
4555
4556 for (fns = Fdefault_value (Qfontification_functions);
4557 CONSP (fns);
4558 fns = XCDR (fns))
4559 {
4560 fn = XCAR (fns);
4561 if (!EQ (fn, Qt))
4562 safe_call1 (fn, pos);
4563 }
4564 }
4565 else
4566 safe_call1 (fn, pos);
4567 }
4568 }
4569
4570 it->f->inhibit_clear_image_cache = saved_inhibit_flag;
4571 unbind_to (count, Qnil);
4572
4573
4574
4575
4576
4577
4578
4579
4580 if (obuf == current_buffer)
4581 {
4582 if (begv == BEGV && zv == ZV)
4583 current_buffer->clip_changed = old_clip_changed;
4584 }
4585
4586
4587 else if (BUFFER_LIVE_P (obuf))
4588 set_buffer_internal_1 (obuf);
4589
4590
4591
4592
4593
4594
4595 it->end_charpos = ZV;
4596
4597
4598
4599
4600 if (!NILP (Fget_char_property (pos, Qfontified, Qnil)))
4601 handled = HANDLED_RECOMPUTE_PROPS;
4602 }
4603
4604 return handled;
4605 }
4606
4607
4608
4609
4610
4611
4612
4613 static int
4614 face_at_pos (const struct it *it, enum lface_attribute_index attr_filter)
4615 {
4616 ptrdiff_t next_stop;
4617
4618 if (!STRINGP (it->string))
4619 {
4620 return face_at_buffer_position (it->w,
4621 IT_CHARPOS (*it),
4622 &next_stop,
4623 (IT_CHARPOS (*it)
4624 + TEXT_PROP_DISTANCE_LIMIT),
4625 false, it->base_face_id,
4626 attr_filter);
4627 }
4628 else
4629 {
4630 int base_face_id;
4631 ptrdiff_t bufpos;
4632 int i;
4633 Lisp_Object from_overlay
4634 = (it->current.overlay_string_index >= 0
4635 ? it->string_overlays[it->current.overlay_string_index
4636 % OVERLAY_STRING_CHUNK_SIZE]
4637 : Qnil);
4638
4639
4640
4641
4642
4643
4644
4645 if (! NILP (from_overlay))
4646 for (i = it->sp - 1; i >= 0; i--)
4647 {
4648 if (it->stack[i].current.overlay_string_index >= 0)
4649 from_overlay
4650 = it->string_overlays[it->stack[i].current.overlay_string_index
4651 % OVERLAY_STRING_CHUNK_SIZE];
4652 else if (! NILP (it->stack[i].from_overlay))
4653 from_overlay = it->stack[i].from_overlay;
4654
4655 if (!NILP (from_overlay))
4656 break;
4657 }
4658
4659 if (! NILP (from_overlay))
4660 {
4661 bufpos = IT_CHARPOS (*it);
4662
4663
4664 base_face_id
4665 = face_for_overlay_string (it->w,
4666 IT_CHARPOS (*it),
4667 &next_stop,
4668 (IT_CHARPOS (*it)
4669 + TEXT_PROP_DISTANCE_LIMIT),
4670 false,
4671 from_overlay, attr_filter);
4672 }
4673 else
4674 {
4675 bufpos = 0;
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
4686
4687
4688
4689
4690
4691
4692
4693 base_face_id = it->string_from_prefix_prop_p
4694 ? (!NILP (Vface_remapping_alist)
4695 ? lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
4696 : DEFAULT_FACE_ID)
4697 : underlying_face_id (it);
4698 }
4699
4700 return face_at_string_position (it->w,
4701 it->string,
4702 IT_STRING_CHARPOS (*it),
4703 bufpos,
4704 &next_stop,
4705 base_face_id, false,
4706 attr_filter);
4707 }
4708 }
4709
4710
4711
4712
4713 static enum prop_handled
4714 handle_face_prop (struct it *it)
4715 {
4716 specpdl_ref count = SPECPDL_INDEX ();
4717
4718
4719
4720 specbind (Qinhibit_quit, Qt);
4721 const int new_face_id = face_at_pos (it, 0);
4722 unbind_to (count, Qnil);
4723
4724
4725
4726
4727
4728
4729
4730
4731 if (new_face_id != it->face_id)
4732 {
4733 struct face *new_face = FACE_FROM_ID (it->f, new_face_id);
4734
4735
4736
4737 struct face *old_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
4738
4739
4740
4741
4742 if (!STRINGP (it->string)
4743 && !old_face
4744 && IT_CHARPOS (*it) > BEG)
4745 {
4746 const int prev_face_id = face_before_it_pos (it);
4747
4748 old_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
4749 }
4750
4751
4752
4753
4754 it->face_id = new_face_id;
4755
4756
4757 if (!(it->start_of_box_run_p && old_face && old_face->box))
4758 it->start_of_box_run_p = (new_face->box != FACE_NO_BOX
4759 && (old_face == NULL || !old_face->box));
4760 it->face_box_p = new_face->box != FACE_NO_BOX;
4761 }
4762
4763 return HANDLED_NORMALLY;
4764 }
4765
4766
4767
4768
4769
4770
4771
4772 static int
4773 underlying_face_id (const struct it *it)
4774 {
4775 int face_id = it->base_face_id, i;
4776
4777 eassert (STRINGP (it->string));
4778
4779 for (i = it->sp - 1; i >= 0; --i)
4780 if (NILP (it->stack[i].string))
4781 face_id = it->stack[i].face_id;
4782
4783 return face_id;
4784 }
4785
4786
4787
4788
4789
4790
4791
4792 static int
4793 face_before_or_after_it_pos (struct it *it, bool before_p)
4794 {
4795 int face_id, limit;
4796 ptrdiff_t next_check_charpos;
4797 struct it it_copy;
4798 void *it_copy_data = NULL;
4799
4800 eassert (it->s == NULL);
4801
4802 if (STRINGP (it->string))
4803 {
4804 ptrdiff_t bufpos, charpos;
4805 int base_face_id;
4806
4807
4808
4809
4810
4811 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string)
4812 || (IT_STRING_CHARPOS (*it) == 0 && before_p)
4813 || it->current_x <= it->first_visible_x)
4814 return it->face_id;
4815
4816 if (!it->bidi_p)
4817 {
4818
4819
4820
4821 if (before_p)
4822 charpos = IT_STRING_CHARPOS (*it) - 1;
4823 else if (it->what == IT_COMPOSITION)
4824
4825
4826 charpos = IT_STRING_CHARPOS (*it) + it->cmp_it.nchars;
4827 else
4828 charpos = IT_STRING_CHARPOS (*it) + 1;
4829 }
4830 else
4831 {
4832
4833
4834
4835
4836
4837
4838
4839
4840
4841
4842 SAVE_IT (it_copy, *it, it_copy_data);
4843 IT_STRING_CHARPOS (it_copy) = 0;
4844 bidi_init_it (0, 0, FRAME_WINDOW_P (it_copy.f), &it_copy.bidi_it);
4845 it_copy.bidi_it.scan_dir = 0;
4846
4847 do
4848 {
4849 charpos = it_copy.bidi_it.charpos;
4850 if (charpos >= SCHARS (it->string))
4851 break;
4852 bidi_move_to_visually_next (&it_copy.bidi_it);
4853 }
4854 while (it_copy.bidi_it.charpos != IT_STRING_CHARPOS (*it));
4855
4856 if (!before_p)
4857 {
4858
4859
4860
4861 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4862
4863
4864
4865 if (it_copy.bidi_it.first_elt)
4866 n++;
4867 while (n--)
4868 bidi_move_to_visually_next (&it_copy.bidi_it);
4869
4870 charpos = it_copy.bidi_it.charpos;
4871 }
4872
4873 RESTORE_IT (it, it, it_copy_data);
4874 }
4875 eassert (0 <= charpos && charpos <= SCHARS (it->string));
4876
4877 if (it->current.overlay_string_index >= 0)
4878 bufpos = IT_CHARPOS (*it);
4879 else
4880 bufpos = 0;
4881
4882 base_face_id = underlying_face_id (it);
4883
4884
4885 face_id = face_at_string_position (it->w, it->string, charpos,
4886 bufpos, &next_check_charpos,
4887 base_face_id, false, 0);
4888
4889
4890
4891
4892 if (STRING_MULTIBYTE (it->string))
4893 {
4894 struct text_pos pos1 = string_pos (charpos, it->string);
4895 const unsigned char *p = SDATA (it->string) + BYTEPOS (pos1);
4896 struct face *face = FACE_FROM_ID (it->f, face_id);
4897 int len, c = check_char_and_length (p, &len);
4898 face_id = FACE_FOR_CHAR (it->f, face, c, charpos, it->string);
4899 }
4900 }
4901 else
4902 {
4903 struct text_pos pos;
4904
4905 if ((IT_CHARPOS (*it) >= ZV && !before_p)
4906 || (IT_CHARPOS (*it) <= BEGV && before_p))
4907 return it->face_id;
4908
4909 limit = IT_CHARPOS (*it) + TEXT_PROP_DISTANCE_LIMIT;
4910 pos = it->current.pos;
4911
4912 if (!it->bidi_p)
4913 {
4914 if (before_p)
4915 DEC_TEXT_POS (pos, it->multibyte_p);
4916 else
4917 {
4918 if (it->what == IT_COMPOSITION)
4919 {
4920
4921
4922 pos.charpos += it->cmp_it.nchars;
4923 pos.bytepos += it->len;
4924 }
4925 else
4926 INC_TEXT_POS (pos, it->multibyte_p);
4927 }
4928 }
4929 else
4930 {
4931 if (before_p)
4932 {
4933 int current_x;
4934
4935
4936
4937
4938
4939
4940
4941
4942
4943
4944 if (it->current_x <= it->first_visible_x)
4945 return it->face_id;
4946 SAVE_IT (it_copy, *it, it_copy_data);
4947
4948
4949
4950
4951
4952 current_x = it_copy.current_x;
4953 move_it_vertically_backward (&it_copy, 0);
4954 move_it_in_display_line (&it_copy, ZV, current_x - 1, MOVE_TO_X);
4955 pos = it_copy.current.pos;
4956 RESTORE_IT (it, it, it_copy_data);
4957 }
4958 else
4959 {
4960
4961
4962
4963 int n = (it->what == IT_COMPOSITION ? it->cmp_it.nchars : 1);
4964
4965 it_copy = *it;
4966
4967
4968
4969 if (it->bidi_it.first_elt)
4970 n++;
4971 while (n--)
4972 bidi_move_to_visually_next (&it_copy.bidi_it);
4973
4974 SET_TEXT_POS (pos,
4975 it_copy.bidi_it.charpos, it_copy.bidi_it.bytepos);
4976 }
4977 }
4978 eassert (BEGV <= CHARPOS (pos) && CHARPOS (pos) <= ZV);
4979
4980
4981 face_id = face_at_buffer_position (it->w,
4982 CHARPOS (pos),
4983 &next_check_charpos,
4984 limit, false, -1, 0);
4985
4986
4987
4988
4989 if (it->multibyte_p)
4990 {
4991 int c = FETCH_MULTIBYTE_CHAR (BYTEPOS (pos));
4992 struct face *face = FACE_FROM_ID (it->f, face_id);
4993 face_id = FACE_FOR_CHAR (it->f, face, c, CHARPOS (pos), Qnil);
4994 }
4995 }
4996
4997 return face_id;
4998 }
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009 static enum prop_handled
5010 handle_invisible_prop (struct it *it)
5011 {
5012 enum prop_handled handled = HANDLED_NORMALLY;
5013 int invis;
5014 Lisp_Object prop;
5015
5016 if (STRINGP (it->string))
5017 {
5018 Lisp_Object end_charpos, limit;
5019
5020
5021
5022
5023 end_charpos = make_fixnum (IT_STRING_CHARPOS (*it));
5024 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5025 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5026
5027 if (invis != 0 && IT_STRING_CHARPOS (*it) < it->end_charpos)
5028 {
5029
5030
5031 bool display_ellipsis_p = (invis == 2);
5032 ptrdiff_t len, endpos;
5033
5034 handled = HANDLED_RECOMPUTE_PROPS;
5035
5036
5037
5038 endpos = len = SCHARS (it->string);
5039 XSETINT (limit, len);
5040 do
5041 {
5042 end_charpos
5043 = Fnext_single_property_change (end_charpos, Qinvisible,
5044 it->string, limit);
5045
5046
5047 eassert (FIXNUMP (end_charpos));
5048 if (FIXNUMP (end_charpos))
5049 {
5050 endpos = XFIXNAT (end_charpos);
5051 prop = Fget_text_property (end_charpos, Qinvisible, it->string);
5052 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5053 if (invis == 2)
5054 display_ellipsis_p = true;
5055 }
5056 else
5057 endpos = len;
5058 }
5059 while (invis != 0 && endpos < len);
5060
5061 if (display_ellipsis_p)
5062 it->ellipsis_p = true;
5063
5064 if (endpos < len)
5065 {
5066
5067 struct text_pos old;
5068 ptrdiff_t oldpos;
5069
5070 old = it->current.string_pos;
5071 oldpos = CHARPOS (old);
5072 if (it->bidi_p)
5073 {
5074 if (it->bidi_it.first_elt
5075 && it->bidi_it.charpos < SCHARS (it->string))
5076 bidi_paragraph_init (it->paragraph_embedding,
5077 &it->bidi_it, true);
5078
5079 do
5080 {
5081 bidi_move_to_visually_next (&it->bidi_it);
5082 }
5083 while (oldpos <= it->bidi_it.charpos
5084 && it->bidi_it.charpos < endpos
5085 && it->bidi_it.charpos < it->bidi_it.string.schars);
5086
5087 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
5088 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
5089 if (IT_CHARPOS (*it) >= endpos)
5090 it->prev_stop = endpos;
5091 }
5092 else
5093 {
5094 IT_STRING_CHARPOS (*it) = endpos;
5095 compute_string_pos (&it->current.string_pos, old, it->string);
5096 }
5097 }
5098 else
5099 {
5100
5101
5102
5103 if (it->current.overlay_string_index >= 0
5104 && !display_ellipsis_p)
5105 {
5106 next_overlay_string (it);
5107
5108
5109 handled = HANDLED_OVERLAY_STRING_CONSUMED;
5110 }
5111 else
5112 {
5113 IT_STRING_CHARPOS (*it) = SCHARS (it->string);
5114 IT_STRING_BYTEPOS (*it) = SBYTES (it->string);
5115 }
5116 }
5117 }
5118 }
5119 else
5120 {
5121 ptrdiff_t newpos, next_stop, start_charpos, tem;
5122 Lisp_Object pos, overlay;
5123
5124
5125 tem = start_charpos = IT_CHARPOS (*it);
5126 pos = make_fixnum (tem);
5127 prop = get_char_property_and_overlay (pos, Qinvisible, it->window,
5128 &overlay);
5129 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5130
5131
5132 if (invis != 0 && start_charpos < it->end_charpos)
5133 {
5134
5135
5136 bool display_ellipsis_p = invis == 2;
5137
5138 handled = HANDLED_RECOMPUTE_PROPS;
5139
5140
5141
5142 do
5143 {
5144
5145
5146
5147
5148
5149 newpos = skip_invisible (tem, &next_stop, ZV, it->window);
5150
5151
5152
5153
5154 if (newpos == tem || newpos >= ZV)
5155 invis = 0;
5156 else
5157 {
5158
5159
5160
5161
5162
5163
5164 pos = make_fixnum (newpos);
5165 prop = Fget_char_property (pos, Qinvisible, it->window);
5166 invis = TEXT_PROP_MEANS_INVISIBLE (prop);
5167 }
5168
5169
5170
5171 if (invis != 0)
5172 tem = next_stop;
5173
5174
5175
5176 if (invis == 2)
5177 display_ellipsis_p = true;
5178 }
5179 while (invis != 0);
5180
5181
5182 if (it->bidi_p)
5183 {
5184 ptrdiff_t bpos = CHAR_TO_BYTE (newpos);
5185 bool on_newline
5186 = bpos == ZV_BYTE || FETCH_BYTE (bpos) == '\n';
5187 bool after_newline
5188 = newpos <= BEGV || FETCH_BYTE (bpos - 1) == '\n';
5189
5190
5191
5192
5193
5194
5195
5196
5197 if (on_newline || after_newline)
5198 {
5199 struct text_pos tpos;
5200 bidi_dir_t pdir = it->bidi_it.paragraph_dir;
5201
5202 SET_TEXT_POS (tpos, newpos, bpos);
5203 reseat_1 (it, tpos, false);
5204
5205
5206
5207
5208
5209 if (on_newline)
5210 {
5211 it->bidi_it.first_elt = false;
5212 it->bidi_it.paragraph_dir = pdir;
5213 it->bidi_it.ch = (bpos == ZV_BYTE) ? -1 : '\n';
5214 it->bidi_it.nchars = 1;
5215 it->bidi_it.ch_len = 1;
5216 }
5217 }
5218 else
5219 {
5220
5221
5222
5223
5224
5225
5226
5227
5228
5229
5230 if (it->bidi_it.first_elt && it->bidi_it.charpos < ZV)
5231 {
5232
5233
5234
5235
5236
5237
5238
5239 bidi_paragraph_init (it->paragraph_embedding,
5240 &it->bidi_it, true);
5241 }
5242 do
5243 {
5244 bidi_move_to_visually_next (&it->bidi_it);
5245 }
5246 while (it->stop_charpos <= it->bidi_it.charpos
5247 && it->bidi_it.charpos < newpos);
5248 IT_CHARPOS (*it) = it->bidi_it.charpos;
5249 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
5250
5251
5252
5253
5254 if (IT_CHARPOS (*it) >= newpos)
5255 it->prev_stop = newpos;
5256 }
5257 }
5258 else
5259 {
5260 IT_CHARPOS (*it) = newpos;
5261 IT_BYTEPOS (*it) = CHAR_TO_BYTE (newpos);
5262 }
5263
5264 if (display_ellipsis_p)
5265 {
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278 if (!STRINGP (it->object))
5279 {
5280 it->position.charpos = newpos - 1;
5281 it->position.bytepos = CHAR_TO_BYTE (it->position.charpos);
5282 }
5283 }
5284
5285
5286
5287
5288
5289
5290
5291 if (NILP (overlay)
5292 && get_overlay_strings (it, it->stop_charpos))
5293 {
5294 handled = HANDLED_RECOMPUTE_PROPS;
5295 if (it->sp > 0)
5296 {
5297 it->stack[it->sp - 1].display_ellipsis_p = display_ellipsis_p;
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310 it->stack[it->sp - 1].stop_charpos
5311 = CHARPOS (it->stack[it->sp - 1].current.pos);
5312 }
5313 }
5314 else if (display_ellipsis_p)
5315 {
5316 it->ellipsis_p = true;
5317
5318
5319
5320 handled = HANDLED_RETURN;
5321 }
5322 }
5323 }
5324
5325 return handled;
5326 }
5327
5328
5329
5330
5331
5332 static void
5333 setup_for_ellipsis (struct it *it, int len)
5334 {
5335
5336
5337 if (it->dp && VECTORP (DISP_INVIS_VECTOR (it->dp)))
5338 {
5339 struct Lisp_Vector *v = XVECTOR (DISP_INVIS_VECTOR (it->dp));
5340 it->dpvec = v->contents;
5341 it->dpend = v->contents + v->header.size;
5342 }
5343 else
5344 {
5345
5346 it->dpvec = default_invis_vector;
5347 it->dpend = default_invis_vector + 3;
5348 }
5349
5350 it->dpvec_char_len = len;
5351 it->current.dpvec_index = 0;
5352 it->dpvec_face_id = -1;
5353
5354
5355
5356
5357
5358
5359
5360
5361 if (it->saved_face_id >= 0)
5362 it->face_id = it->saved_face_id;
5363
5364
5365
5366 if (it->method == GET_FROM_BUFFER)
5367 it->ignore_overlay_strings_at_pos_p = false;
5368
5369 it->method = GET_FROM_DISPLAY_VECTOR;
5370 it->ellipsis_p = true;
5371 }
5372
5373
5374 static Lisp_Object
5375 find_display_property (Lisp_Object disp, Lisp_Object prop)
5376 {
5377 if (NILP (disp))
5378 return Qnil;
5379
5380 if (VECTORP (disp))
5381 {
5382 for (ptrdiff_t i = 0; i < ASIZE (disp); i++)
5383 {
5384 Lisp_Object elem = AREF (disp, i);
5385 if (CONSP (elem)
5386 && CONSP (XCDR (elem))
5387 && EQ (XCAR (elem), prop))
5388 return XCAR (XCDR (elem));
5389 }
5390 return Qnil;
5391 }
5392
5393 else if (CONSP (disp)
5394 && CONSP (XCAR (disp)))
5395 {
5396 while (!NILP (disp))
5397 {
5398 Lisp_Object elem = XCAR (disp);
5399 if (CONSP (elem)
5400 && CONSP (XCDR (elem))
5401 && EQ (XCAR (elem), prop))
5402 return XCAR (XCDR (elem));
5403
5404
5405
5406 if (CONSP (XCDR (disp)))
5407 disp = XCDR (disp);
5408 else
5409 disp = Qnil;
5410 }
5411 return Qnil;
5412 }
5413
5414 else if (CONSP (disp)
5415 && CONSP (XCDR (disp))
5416 && EQ (XCAR (disp), prop))
5417 return XCAR (XCDR (disp));
5418 else
5419 return Qnil;
5420 }
5421
5422 static Lisp_Object
5423 get_display_property (ptrdiff_t bufpos, Lisp_Object prop, Lisp_Object object)
5424 {
5425 return find_display_property (Fget_text_property (make_fixnum (bufpos),
5426 Qdisplay, object),
5427 prop);
5428 }
5429
5430 static void
5431 display_min_width (struct it *it, ptrdiff_t bufpos,
5432 Lisp_Object object, Lisp_Object width_spec)
5433 {
5434
5435
5436 if (!NILP (it->min_width_property)
5437 && !EQ (width_spec, it->min_width_property))
5438 {
5439 if (!it->glyph_row)
5440 return;
5441
5442
5443
5444
5445
5446 if ((bufpos == 0
5447 && !EQ (it->min_width_property,
5448 get_display_property (0, Qmin_width, object)))
5449
5450
5451 || (bufpos > BEGV
5452 && EQ (it->min_width_property,
5453 get_display_property (bufpos - 1, Qmin_width, object))))
5454 {
5455 Lisp_Object w = Qnil;
5456 double width;
5457 #ifdef HAVE_WINDOW_SYSTEM
5458 if (FRAME_WINDOW_P (it->f))
5459 {
5460 struct font *font = NULL;
5461 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5462 font = face->font ? face->font : FRAME_FONT (it->f);
5463 calc_pixel_width_or_height (&width, it,
5464 XCAR (it->min_width_property),
5465 font, true, NULL);
5466 width -= it->current_x - it->min_width_start;
5467 w = list1 (make_int (width));
5468 }
5469 else
5470 #endif
5471 {
5472 calc_pixel_width_or_height (&width, it,
5473 XCAR (it->min_width_property),
5474 NULL, true, NULL);
5475 width -= (it->current_x - it->min_width_start) /
5476 FRAME_COLUMN_WIDTH (it->f);
5477 w = make_int (width);
5478 }
5479
5480
5481 it->object = list3 (Qspace, QCwidth, w);
5482 produce_stretch_glyph (it);
5483 if (it->area == TEXT_AREA)
5484 it->current_x += it->pixel_width;
5485 it->min_width_property = Qnil;
5486 }
5487 }
5488
5489
5490
5491
5492 if (CONSP (width_spec))
5493 {
5494 if (bufpos == BEGV
5495
5496 || (bufpos == 0
5497 && !EQ (it->min_width_property,
5498 get_display_property (0, Qmin_width, object)))
5499
5500 || (bufpos > BEGV
5501 && !EQ (width_spec,
5502 get_display_property (bufpos - 1, Qmin_width, object))))
5503 {
5504 it->min_width_property = width_spec;
5505 it->min_width_start = it->current_x;
5506 }
5507 }
5508 }
5509
5510 DEFUN ("get-display-property", Fget_display_property,
5511 Sget_display_property, 2, 4, 0,
5512 doc:
5513
5514
5515
5516
5517 )
5518 (Lisp_Object position, Lisp_Object prop, Lisp_Object object,
5519 Lisp_Object properties)
5520 {
5521 if (NILP (properties))
5522 properties = Fget_text_property (position, Qdisplay, object);
5523 else
5524 CHECK_LIST (properties);
5525
5526 return find_display_property (properties, prop);
5527 }
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541 static enum prop_handled
5542 handle_display_prop (struct it *it)
5543 {
5544 Lisp_Object propval, object, overlay;
5545 struct text_pos *position;
5546 ptrdiff_t bufpos;
5547
5548 int display_replaced = 0;
5549
5550 if (STRINGP (it->string))
5551 {
5552 object = it->string;
5553 position = &it->current.string_pos;
5554 bufpos = CHARPOS (it->current.pos);
5555 }
5556 else
5557 {
5558 XSETWINDOW (object, it->w);
5559 position = &it->current.pos;
5560 bufpos = CHARPOS (*position);
5561 }
5562
5563
5564 it->slice.x = it->slice.y = it->slice.width = it->slice.height = Qnil;
5565 it->space_width = Qnil;
5566 it->font_height = Qnil;
5567 it->voffset = 0;
5568
5569
5570
5571
5572 if (!it->string_from_display_prop_p)
5573 it->area = TEXT_AREA;
5574
5575 propval = get_char_property_and_overlay (make_fixnum (position->charpos),
5576 Qdisplay, object, &overlay);
5577
5578
5579 if (!STRINGP (it->string))
5580 object = it->w->contents;
5581
5582
5583 if (!NILP (it->min_width_property)
5584 && NILP (find_display_property (propval, Qmin_width)))
5585 display_min_width (it, bufpos, object, Qnil);
5586
5587 if (NILP (propval))
5588 return HANDLED_NORMALLY;
5589
5590
5591
5592 display_replaced = handle_display_spec (it, propval, object, overlay,
5593 position, bufpos,
5594 FRAME_WINDOW_P (it->f));
5595 return display_replaced != 0 ? HANDLED_RETURN : HANDLED_NORMALLY;
5596 }
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614 static int
5615 handle_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5616 Lisp_Object overlay, struct text_pos *position,
5617 ptrdiff_t bufpos, bool frame_window_p)
5618 {
5619 int replacing = 0;
5620 bool enable_eval = true;
5621
5622
5623 if (CONSP (spec) && EQ (XCAR (spec), Qdisable_eval))
5624 {
5625 enable_eval = false;
5626 spec = CONSP (XCDR (spec)) ? XCAR (XCDR (spec)) : Qnil;
5627 }
5628
5629 if (CONSP (spec)
5630
5631 && !EQ (XCAR (spec), Qimage)
5632 #ifdef HAVE_XWIDGETS
5633 && !EQ (XCAR (spec), Qxwidget)
5634 #endif
5635 && !EQ (XCAR (spec), Qspace)
5636 && !EQ (XCAR (spec), Qwhen)
5637 && !EQ (XCAR (spec), Qslice)
5638 && !EQ (XCAR (spec), Qspace_width)
5639 && !EQ (XCAR (spec), Qheight)
5640 && !EQ (XCAR (spec), Qraise)
5641
5642 && !(CONSP (XCAR (spec)) && EQ (XCAR (XCAR (spec)), Qmargin))
5643 && !EQ (XCAR (spec), Qleft_fringe)
5644 && !EQ (XCAR (spec), Qright_fringe)
5645 && !EQ (XCAR (spec), Qmin_width)
5646 && !NILP (XCAR (spec)))
5647 {
5648 for (; CONSP (spec); spec = XCDR (spec))
5649 {
5650 int rv = handle_single_display_spec (it, XCAR (spec), object,
5651 overlay, position, bufpos,
5652 replacing, frame_window_p,
5653 enable_eval);
5654 if (rv != 0)
5655 {
5656 replacing = rv;
5657
5658
5659 if (!it || STRINGP (object))
5660 break;
5661 }
5662 }
5663 }
5664 else if (VECTORP (spec))
5665 {
5666 ptrdiff_t i;
5667 for (i = 0; i < ASIZE (spec); ++i)
5668 {
5669 int rv = handle_single_display_spec (it, AREF (spec, i), object,
5670 overlay, position, bufpos,
5671 replacing, frame_window_p,
5672 enable_eval);
5673 if (rv != 0)
5674 {
5675 replacing = rv;
5676
5677
5678 if (!it || STRINGP (object))
5679 break;
5680 }
5681 }
5682 }
5683 else
5684 replacing = handle_single_display_spec (it, spec, object, overlay, position,
5685 bufpos, 0, frame_window_p,
5686 enable_eval);
5687 return replacing;
5688 }
5689
5690
5691
5692
5693 static struct text_pos
5694 display_prop_end (struct it *it, Lisp_Object object, struct text_pos start_pos)
5695 {
5696 Lisp_Object end;
5697 struct text_pos end_pos;
5698
5699 end = Fnext_single_char_property_change (make_fixnum (CHARPOS (start_pos)),
5700 Qdisplay, object, Qnil);
5701 CHARPOS (end_pos) = XFIXNAT (end);
5702 if (STRINGP (object))
5703 compute_string_pos (&end_pos, start_pos, it->string);
5704 else
5705 BYTEPOS (end_pos) = CHAR_TO_BYTE (XFIXNAT (end));
5706
5707 return end_pos;
5708 }
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736 static int
5737 handle_single_display_spec (struct it *it, Lisp_Object spec, Lisp_Object object,
5738 Lisp_Object overlay, struct text_pos *position,
5739 ptrdiff_t bufpos, int display_replaced,
5740 bool frame_window_p, bool enable_eval_p)
5741 {
5742 Lisp_Object form;
5743 Lisp_Object location, value;
5744 struct text_pos start_pos = *position;
5745 void *itdata = NULL;
5746
5747
5748
5749 form = Qt;
5750 if (CONSP (spec) && EQ (XCAR (spec), Qwhen))
5751 {
5752 spec = XCDR (spec);
5753 if (!CONSP (spec))
5754 return 0;
5755 form = XCAR (spec);
5756 spec = XCDR (spec);
5757 }
5758
5759 if (!NILP (form) && !EQ (form, Qt) && !enable_eval_p)
5760 form = Qnil;
5761 if (!NILP (form) && !EQ (form, Qt))
5762 {
5763 specpdl_ref count = SPECPDL_INDEX ();
5764
5765
5766
5767
5768
5769
5770 if (NILP (object))
5771 XSETBUFFER (object, current_buffer);
5772 specbind (Qobject, object);
5773 specbind (Qposition, make_fixnum (CHARPOS (*position)));
5774 specbind (Qbuffer_position, make_fixnum (bufpos));
5775
5776
5777 itdata = bidi_shelve_cache ();
5778 form = safe_eval (form);
5779 bidi_unshelve_cache (itdata, false);
5780 form = unbind_to (count, form);
5781 }
5782
5783 if (NILP (form))
5784 return 0;
5785
5786
5787 if (CONSP (spec)
5788 && EQ (XCAR (spec), Qheight)
5789 && CONSP (XCDR (spec)))
5790 {
5791 if (it)
5792 {
5793 if (!FRAME_WINDOW_P (it->f))
5794 return 0;
5795
5796 it->font_height = XCAR (XCDR (spec));
5797 if (!NILP (it->font_height))
5798 {
5799 int new_height = -1;
5800
5801 if (CONSP (it->font_height)
5802 && (EQ (XCAR (it->font_height), Qplus)
5803 || EQ (XCAR (it->font_height), Qminus))
5804 && CONSP (XCDR (it->font_height))
5805 && RANGED_FIXNUMP (0, XCAR (XCDR (it->font_height)), INT_MAX))
5806 {
5807
5808 int steps = XFIXNUM (XCAR (XCDR (it->font_height)));
5809 if (EQ (XCAR (it->font_height), Qplus))
5810 steps = - steps;
5811 it->face_id = smaller_face (it->f, it->face_id, steps);
5812 }
5813 else if (FUNCTIONP (it->font_height) && enable_eval_p)
5814 {
5815
5816
5817 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5818 Lisp_Object height;
5819 itdata = bidi_shelve_cache ();
5820 height = safe_call1 (it->font_height,
5821 face->lface[LFACE_HEIGHT_INDEX]);
5822 bidi_unshelve_cache (itdata, false);
5823 if (NUMBERP (height))
5824 new_height = XFLOATINT (height);
5825 }
5826 else if (NUMBERP (it->font_height))
5827 {
5828
5829 struct face *f;
5830
5831 f = FACE_FROM_ID (it->f,
5832 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID));
5833 new_height = (XFLOATINT (it->font_height)
5834 * XFIXNUM (f->lface[LFACE_HEIGHT_INDEX]));
5835 }
5836 else if (enable_eval_p)
5837 {
5838
5839
5840 specpdl_ref count = SPECPDL_INDEX ();
5841 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5842
5843 specbind (Qheight, face->lface[LFACE_HEIGHT_INDEX]);
5844 itdata = bidi_shelve_cache ();
5845 value = safe_eval (it->font_height);
5846 bidi_unshelve_cache (itdata, false);
5847 value = unbind_to (count, value);
5848
5849 if (NUMBERP (value))
5850 new_height = XFLOATINT (value);
5851 }
5852
5853 if (new_height > 0)
5854 it->face_id = face_with_height (it->f, it->face_id, new_height);
5855 }
5856 }
5857
5858 return 0;
5859 }
5860
5861
5862 if (CONSP (spec)
5863 && EQ (XCAR (spec), Qspace_width)
5864 && CONSP (XCDR (spec)))
5865 {
5866 if (it)
5867 {
5868 if (!FRAME_WINDOW_P (it->f))
5869 return 0;
5870
5871 value = XCAR (XCDR (spec));
5872 if (NUMBERP (value) && XFLOATINT (value) > 0)
5873 it->space_width = value;
5874 }
5875
5876 return 0;
5877 }
5878
5879
5880 if (CONSP (spec)
5881 && EQ (XCAR (spec), Qmin_width)
5882 && CONSP (XCDR (spec))
5883 && CONSP (XCAR (XCDR (spec))))
5884 {
5885 if (it)
5886 display_min_width (it, bufpos, object, XCAR (XCDR (spec)));
5887 return 0;
5888 }
5889
5890
5891 if (CONSP (spec)
5892 && EQ (XCAR (spec), Qslice))
5893 {
5894 Lisp_Object tem;
5895
5896 if (it)
5897 {
5898 if (!FRAME_WINDOW_P (it->f))
5899 return 0;
5900
5901 if (tem = XCDR (spec), CONSP (tem))
5902 {
5903 it->slice.x = XCAR (tem);
5904 if (tem = XCDR (tem), CONSP (tem))
5905 {
5906 it->slice.y = XCAR (tem);
5907 if (tem = XCDR (tem), CONSP (tem))
5908 {
5909 it->slice.width = XCAR (tem);
5910 if (tem = XCDR (tem), CONSP (tem))
5911 it->slice.height = XCAR (tem);
5912 }
5913 }
5914 }
5915 }
5916
5917 return 0;
5918 }
5919
5920
5921 if (CONSP (spec)
5922 && EQ (XCAR (spec), Qraise)
5923 && CONSP (XCDR (spec)))
5924 {
5925 if (it)
5926 {
5927 if (!FRAME_WINDOW_P (it->f))
5928 return 0;
5929
5930 #ifdef HAVE_WINDOW_SYSTEM
5931 value = XCAR (XCDR (spec));
5932 if (NUMBERP (value))
5933 {
5934 struct face *face = FACE_FROM_ID (it->f, it->face_id);
5935 it->voffset = - (XFLOATINT (value)
5936 * (normal_char_height (face->font, -1)));
5937 }
5938 #endif
5939 }
5940
5941 return 0;
5942 }
5943
5944
5945
5946 if (it && it->string_from_display_prop_p)
5947 return 0;
5948
5949
5950
5951 if (it)
5952 {
5953 start_pos = *position;
5954 *position = display_prop_end (it, object, start_pos);
5955
5956
5957
5958
5959
5960
5961
5962 if (!NILP (overlay))
5963 {
5964 ptrdiff_t ovendpos = OVERLAY_END (overlay);
5965
5966
5967
5968
5969
5970
5971
5972 ovendpos = clip_to_bounds (BEGV, ovendpos, ZV);
5973
5974 if (ovendpos > CHARPOS (*position))
5975 SET_TEXT_POS (*position, ovendpos, CHAR_TO_BYTE (ovendpos));
5976 }
5977 }
5978 value = Qnil;
5979
5980
5981
5982 if (it)
5983 it->stop_charpos = position->charpos;
5984
5985
5986
5987 if (CONSP (spec)
5988 && (EQ (XCAR (spec), Qleft_fringe)
5989 || EQ (XCAR (spec), Qright_fringe))
5990 && CONSP (XCDR (spec)))
5991 {
5992 if (it)
5993 {
5994 if (!FRAME_WINDOW_P (it->f))
5995
5996
5997 {
5998
5999
6000
6001
6002 if (it->bidi_p)
6003 {
6004 it->position = *position;
6005 iterate_out_of_display_property (it);
6006 *position = it->position;
6007 }
6008 return 1;
6009 }
6010 }
6011 else if (!frame_window_p)
6012 return 1;
6013
6014 #ifdef HAVE_WINDOW_SYSTEM
6015 value = XCAR (XCDR (spec));
6016 int fringe_bitmap = SYMBOLP (value) ? lookup_fringe_bitmap (value) : 0;
6017 if (! fringe_bitmap)
6018
6019
6020 {
6021 if (it && it->bidi_p)
6022 {
6023 it->position = *position;
6024 iterate_out_of_display_property (it);
6025 *position = it->position;
6026 }
6027 return 1;
6028 }
6029
6030 if (it)
6031 {
6032 int face_id = lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
6033
6034 if (CONSP (XCDR (XCDR (spec))))
6035 {
6036 Lisp_Object face_name = XCAR (XCDR (XCDR (spec)));
6037 int face_id2;
6038
6039
6040
6041 specpdl_ref count1 = SPECPDL_INDEX ();
6042 specbind (Qinhibit_quit, Qt);
6043 face_id2 = lookup_derived_face (it->w, it->f, face_name,
6044 FRINGE_FACE_ID, false);
6045 unbind_to (count1, Qnil);
6046 if (face_id2 >= 0)
6047 face_id = face_id2;
6048 }
6049
6050
6051
6052 push_it (it, position);
6053
6054 it->area = TEXT_AREA;
6055 it->what = IT_IMAGE;
6056 it->image_id = -1;
6057 it->position = start_pos;
6058 it->object = NILP (object) ? it->w->contents : object;
6059 it->method = GET_FROM_IMAGE;
6060 it->from_overlay = Qnil;
6061 it->face_id = face_id;
6062 it->from_disp_prop_p = true;
6063
6064
6065
6066
6067 *position = start_pos;
6068
6069 if (EQ (XCAR (spec), Qleft_fringe))
6070 {
6071 it->left_user_fringe_bitmap = fringe_bitmap;
6072 it->left_user_fringe_face_id = face_id;
6073 }
6074 else
6075 {
6076 it->right_user_fringe_bitmap = fringe_bitmap;
6077 it->right_user_fringe_face_id = face_id;
6078 }
6079 }
6080 #endif
6081 return 1;
6082 }
6083
6084
6085
6086
6087 location = Qunbound;
6088 if (CONSP (spec) && CONSP (XCAR (spec)))
6089 {
6090 Lisp_Object tem;
6091
6092 value = XCDR (spec);
6093 if (CONSP (value))
6094 value = XCAR (value);
6095
6096 tem = XCAR (spec);
6097 if (EQ (XCAR (tem), Qmargin)
6098 && (tem = XCDR (tem),
6099 tem = CONSP (tem) ? XCAR (tem) : Qnil,
6100 (NILP (tem)
6101 || EQ (tem, Qleft_margin)
6102 || EQ (tem, Qright_margin))))
6103 location = tem;
6104 }
6105
6106 if (BASE_EQ (location, Qunbound))
6107 {
6108 location = Qnil;
6109 value = spec;
6110 }
6111
6112
6113
6114
6115
6116
6117
6118
6119 bool valid_p = (STRINGP (value)
6120 #ifdef HAVE_WINDOW_SYSTEM
6121 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6122 && valid_image_p (value))
6123 #endif
6124 || (CONSP (value) && EQ (XCAR (value), Qspace))
6125 || ((it ? FRAME_WINDOW_P (it->f) : frame_window_p)
6126 && valid_xwidget_spec_p (value)));
6127
6128 if (valid_p && display_replaced == 0)
6129 {
6130 int retval = 1;
6131
6132 if (!it)
6133 {
6134
6135
6136
6137 if (CONSP (value) && EQ (XCAR (value), Qspace) && NILP (location))
6138 retval = 2;
6139 return retval;
6140 }
6141
6142
6143
6144 push_it (it, position);
6145 it->from_overlay = overlay;
6146 it->from_disp_prop_p = true;
6147
6148 if (NILP (location))
6149 it->area = TEXT_AREA;
6150 else if (EQ (location, Qleft_margin))
6151 it->area = LEFT_MARGIN_AREA;
6152 else
6153 it->area = RIGHT_MARGIN_AREA;
6154
6155 if (STRINGP (value))
6156 {
6157 it->string = value;
6158 it->multibyte_p = STRING_MULTIBYTE (it->string);
6159 it->current.overlay_string_index = -1;
6160 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6161 it->end_charpos = it->string_nchars = SCHARS (it->string);
6162 it->method = GET_FROM_STRING;
6163 it->stop_charpos = 0;
6164 it->prev_stop = 0;
6165 it->base_level_stop = 0;
6166 it->string_from_display_prop_p = true;
6167 it->cmp_it.id = -1;
6168
6169
6170
6171 if (BUFFERP (object))
6172 *position = start_pos;
6173
6174
6175
6176
6177 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6178 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6179 else
6180 it->paragraph_embedding = L2R;
6181
6182
6183 if (it->bidi_p)
6184 {
6185 it->bidi_it.string.lstring = it->string;
6186 it->bidi_it.string.s = NULL;
6187 it->bidi_it.string.schars = it->end_charpos;
6188 it->bidi_it.string.bufpos = bufpos;
6189 it->bidi_it.string.from_disp_str = true;
6190 it->bidi_it.string.unibyte = !it->multibyte_p;
6191 it->bidi_it.w = it->w;
6192 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6193 }
6194 }
6195 else if (CONSP (value) && EQ (XCAR (value), Qspace))
6196 {
6197 it->method = GET_FROM_STRETCH;
6198 it->object = value;
6199 *position = it->position = start_pos;
6200 retval = 1 + (it->area == TEXT_AREA);
6201 }
6202 else if (valid_xwidget_spec_p (value))
6203 {
6204 it->what = IT_XWIDGET;
6205 it->method = GET_FROM_XWIDGET;
6206 it->position = start_pos;
6207 it->object = NILP (object) ? it->w->contents : object;
6208 *position = start_pos;
6209 it->xwidget = lookup_xwidget (value);
6210 }
6211 #ifdef HAVE_WINDOW_SYSTEM
6212 else
6213 {
6214 specpdl_ref count = SPECPDL_INDEX ();
6215
6216 it->what = IT_IMAGE;
6217
6218
6219
6220 specbind (Qinhibit_quit, Qt);
6221 it->image_id = lookup_image (it->f, value, it->face_id);
6222 unbind_to (count, Qnil);
6223 it->position = start_pos;
6224 it->object = NILP (object) ? it->w->contents : object;
6225 it->method = GET_FROM_IMAGE;
6226
6227
6228
6229
6230 *position = start_pos;
6231 }
6232 #endif
6233
6234 return retval;
6235 }
6236
6237
6238
6239 *position = start_pos;
6240 return 0;
6241 }
6242
6243
6244
6245
6246
6247
6248 bool
6249 display_prop_intangible_p (Lisp_Object prop, Lisp_Object overlay,
6250 ptrdiff_t charpos, ptrdiff_t bytepos)
6251 {
6252 bool frame_window_p = FRAME_WINDOW_P (XFRAME (selected_frame));
6253 struct text_pos position;
6254
6255 SET_TEXT_POS (position, charpos, bytepos);
6256 return (handle_display_spec (NULL, prop, Qnil, overlay,
6257 &position, charpos, frame_window_p)
6258 != 0);
6259 }
6260
6261
6262
6263
6264
6265
6266
6267
6268
6269
6270 static bool
6271 single_display_spec_string_p (Lisp_Object prop, Lisp_Object string)
6272 {
6273 if (EQ (string, prop))
6274 return true;
6275
6276
6277 if (CONSP (prop) && EQ (XCAR (prop), Qwhen))
6278 {
6279 prop = XCDR (prop);
6280 if (!CONSP (prop))
6281 return false;
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292 prop = XCDR (prop);
6293 }
6294
6295 if (CONSP (prop))
6296
6297 if (EQ (XCAR (prop), Qmargin))
6298 {
6299 prop = XCDR (prop);
6300 if (!CONSP (prop))
6301 return false;
6302
6303 prop = XCDR (prop);
6304 if (!CONSP (prop))
6305 return false;
6306 }
6307
6308 return EQ (prop, string) || (CONSP (prop) && EQ (XCAR (prop), string));
6309 }
6310
6311
6312
6313
6314 static bool
6315 display_prop_string_p (Lisp_Object prop, Lisp_Object string)
6316 {
6317 if (CONSP (prop)
6318 && !EQ (XCAR (prop), Qwhen)
6319 && !(CONSP (XCAR (prop)) && EQ (Qmargin, XCAR (XCAR (prop)))))
6320 {
6321
6322 while (CONSP (prop))
6323 {
6324 if (single_display_spec_string_p (XCAR (prop), string))
6325 return true;
6326 prop = XCDR (prop);
6327 }
6328 }
6329 else if (VECTORP (prop))
6330 {
6331
6332 ptrdiff_t i;
6333 for (i = 0; i < ASIZE (prop); ++i)
6334 if (single_display_spec_string_p (AREF (prop, i), string))
6335 return true;
6336 }
6337 else
6338 return single_display_spec_string_p (prop, string);
6339
6340 return false;
6341 }
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353 static ptrdiff_t
6354 string_buffer_position_lim (Lisp_Object string,
6355 ptrdiff_t from, ptrdiff_t to, bool back_p)
6356 {
6357 Lisp_Object limit, prop, pos;
6358 bool found = false;
6359
6360 pos = make_fixnum (max (from, BEGV));
6361
6362 if (!back_p)
6363 {
6364 limit = make_fixnum (min (to, ZV));
6365 while (!found && !EQ (pos, limit))
6366 {
6367 prop = Fget_char_property (pos, Qdisplay, Qnil);
6368 if (!NILP (prop) && display_prop_string_p (prop, string))
6369 found = true;
6370 else
6371 pos = Fnext_single_char_property_change (pos, Qdisplay, Qnil,
6372 limit);
6373 }
6374 }
6375 else
6376 {
6377 limit = make_fixnum (max (to, BEGV));
6378 while (!found && !EQ (pos, limit))
6379 {
6380 prop = Fget_char_property (pos, Qdisplay, Qnil);
6381 if (!NILP (prop) && display_prop_string_p (prop, string))
6382 found = true;
6383 else
6384 pos = Fprevious_single_char_property_change (pos, Qdisplay, Qnil,
6385 limit);
6386 }
6387 }
6388
6389 return found ? XFIXNUM (pos) : 0;
6390 }
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401 static ptrdiff_t
6402 string_buffer_position (Lisp_Object string, ptrdiff_t around_charpos)
6403 {
6404 const int MAX_DISTANCE = 1000;
6405 ptrdiff_t forward_limit = min (around_charpos + MAX_DISTANCE, ZV);
6406 ptrdiff_t found = string_buffer_position_lim (string, around_charpos,
6407 forward_limit, false);
6408
6409 if (!found)
6410 {
6411 ptrdiff_t backward_limit = max (around_charpos - MAX_DISTANCE, BEGV);
6412 found = string_buffer_position_lim (string, around_charpos,
6413 backward_limit, true);
6414 }
6415 return found;
6416 }
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427 static enum prop_handled
6428 handle_composition_prop (struct it *it)
6429 {
6430 Lisp_Object prop, string;
6431 ptrdiff_t pos, pos_byte, start, end;
6432
6433 if (STRINGP (it->string))
6434 {
6435 unsigned char *s;
6436
6437 pos = IT_STRING_CHARPOS (*it);
6438 pos_byte = IT_STRING_BYTEPOS (*it);
6439 string = it->string;
6440 s = SDATA (string) + pos_byte;
6441 if (STRING_MULTIBYTE (string))
6442 it->c = STRING_CHAR (s);
6443 else
6444 it->c = *s;
6445 }
6446 else
6447 {
6448 pos = IT_CHARPOS (*it);
6449 pos_byte = IT_BYTEPOS (*it);
6450 string = Qnil;
6451 it->c = FETCH_CHAR (pos_byte);
6452 }
6453
6454
6455
6456
6457 if (find_composition (pos, -1, &start, &end, &prop, string)
6458 && composition_valid_p (start, end, prop)
6459 && (STRINGP (it->string) || (PT <= start || PT >= end)))
6460 {
6461 if (start < pos)
6462
6463
6464
6465 return HANDLED_NORMALLY;
6466 if (start != pos)
6467 {
6468 if (STRINGP (it->string))
6469 pos_byte = string_char_to_byte (it->string, start);
6470 else
6471 pos_byte = CHAR_TO_BYTE (start);
6472 }
6473 it->cmp_it.id = get_composition_id (start, pos_byte, end - start,
6474 prop, string);
6475
6476 if (it->cmp_it.id >= 0)
6477 {
6478 it->cmp_it.ch = -1;
6479 it->cmp_it.nchars = COMPOSITION_LENGTH (prop);
6480 it->cmp_it.nglyphs = -1;
6481 }
6482 }
6483
6484 return HANDLED_NORMALLY;
6485 }
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496 struct overlay_entry
6497 {
6498 Lisp_Object overlay;
6499 Lisp_Object string;
6500 EMACS_INT priority;
6501 bool after_string_p;
6502 };
6503
6504
6505
6506
6507
6508 static enum prop_handled
6509 handle_overlay_change (struct it *it)
6510 {
6511 if (!STRINGP (it->string) && get_overlay_strings (it, 0))
6512 return HANDLED_RECOMPUTE_PROPS;
6513 else
6514 return HANDLED_NORMALLY;
6515 }
6516
6517
6518
6519
6520
6521
6522
6523
6524
6525 static void
6526 next_overlay_string (struct it *it)
6527 {
6528 ++it->current.overlay_string_index;
6529 if (it->current.overlay_string_index == it->n_overlay_strings)
6530 {
6531
6532
6533
6534
6535 it->ellipsis_p = it->stack[it->sp - 1].display_ellipsis_p;
6536 pop_it (it);
6537 eassert (it->sp > 0
6538 || (NILP (it->string)
6539 && it->method == GET_FROM_BUFFER
6540 && it->stop_charpos >= BEGV
6541 && it->stop_charpos <= it->end_charpos));
6542 it->current.overlay_string_index = -1;
6543 it->n_overlay_strings = 0;
6544
6545
6546
6547
6548 if (it->sp > 0 && STRINGP (it->string) && !SCHARS (it->string))
6549 pop_it (it);
6550
6551
6552
6553
6554
6555
6556
6557
6558
6559 if (it->overlay_strings_charpos == IT_CHARPOS (*it))
6560 it->ignore_overlay_strings_at_pos_p = true;
6561
6562
6563
6564
6565 if (NILP (it->string)
6566 && IT_CHARPOS (*it) >= it->end_charpos
6567 && it->overlay_strings_charpos >= it->end_charpos)
6568 it->overlay_strings_at_end_processed_p = true;
6569
6570
6571
6572
6573
6574
6575
6576 it->overlay_strings_charpos = -1;
6577 }
6578 else
6579 {
6580
6581
6582
6583
6584
6585
6586 int i = it->current.overlay_string_index % OVERLAY_STRING_CHUNK_SIZE;
6587
6588 if (it->current.overlay_string_index && i == 0)
6589 load_overlay_strings (it, it->overlay_strings_charpos);
6590
6591
6592
6593 it->string = it->overlay_strings[i];
6594 it->multibyte_p = STRING_MULTIBYTE (it->string);
6595 SET_TEXT_POS (it->current.string_pos, 0, 0);
6596 it->method = GET_FROM_STRING;
6597 it->stop_charpos = 0;
6598 it->end_charpos = SCHARS (it->string);
6599 if (it->cmp_it.stop_pos >= 0)
6600 it->cmp_it.stop_pos = 0;
6601 it->prev_stop = 0;
6602 it->base_level_stop = 0;
6603
6604
6605 if (it->bidi_p)
6606 {
6607 it->bidi_it.string.lstring = it->string;
6608 it->bidi_it.string.s = NULL;
6609 it->bidi_it.string.schars = SCHARS (it->string);
6610 it->bidi_it.string.bufpos = it->overlay_strings_charpos;
6611 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6612 it->bidi_it.string.unibyte = !it->multibyte_p;
6613 it->bidi_it.w = it->w;
6614 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6615 }
6616 }
6617
6618 CHECK_IT (it);
6619 }
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
6631
6632
6633
6634
6635
6636
6637
6638 static int
6639 compare_overlay_entries (const void *e1, const void *e2)
6640 {
6641 struct overlay_entry const *entry1 = e1;
6642 struct overlay_entry const *entry2 = e2;
6643 int result;
6644
6645 if (entry1->after_string_p != entry2->after_string_p)
6646 {
6647
6648
6649 if (EQ (entry1->overlay, entry2->overlay))
6650 result = entry1->after_string_p ? 1 : -1;
6651 else
6652 result = entry1->after_string_p ? -1 : 1;
6653 }
6654 else if (entry1->priority != entry2->priority)
6655 {
6656 if (entry1->after_string_p)
6657
6658 result = entry2->priority < entry1->priority ? -1 : 1;
6659 else
6660
6661 result = entry1->priority < entry2->priority ? -1 : 1;
6662 }
6663 else
6664 result = 0;
6665
6666 return result;
6667 }
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694 static void
6695 load_overlay_strings (struct it *it, ptrdiff_t charpos)
6696 {
6697 ptrdiff_t n = 0;
6698 struct overlay_entry entriesbuf[20];
6699 ptrdiff_t size = ARRAYELTS (entriesbuf);
6700 struct overlay_entry *entries = entriesbuf;
6701 struct itree_node *node;
6702
6703 USE_SAFE_ALLOCA;
6704
6705 if (charpos <= 0)
6706 charpos = IT_CHARPOS (*it);
6707
6708
6709
6710
6711
6712 #define RECORD_OVERLAY_STRING(OVERLAY, STRING, AFTER_P) \
6713 do \
6714 { \
6715 Lisp_Object priority; \
6716 \
6717 if (n == size) \
6718 { \
6719 struct overlay_entry *old = entries; \
6720 SAFE_NALLOCA (entries, 2, size); \
6721 memcpy (entries, old, size * sizeof *entries); \
6722 size *= 2; \
6723 } \
6724 \
6725 entries[n].string = (STRING); \
6726 entries[n].overlay = (OVERLAY); \
6727 priority = Foverlay_get ((OVERLAY), Qpriority); \
6728 entries[n].priority = FIXNUMP (priority) ? XFIXNUM (priority) : 0; \
6729 entries[n].after_string_p = (AFTER_P); \
6730 ++n; \
6731 } \
6732 while (false)
6733
6734
6735
6736 ITREE_FOREACH (node, current_buffer->overlays, charpos - 1, charpos + 1, DESCENDING)
6737 {
6738 Lisp_Object overlay = node->data;
6739 eassert (OVERLAYP (overlay));
6740 ptrdiff_t start = node->begin;
6741 ptrdiff_t end = node->end;
6742
6743
6744
6745 if (end != charpos && start != charpos)
6746 continue;
6747
6748
6749 Lisp_Object window = Foverlay_get (overlay, Qwindow);
6750 if (WINDOWP (window) && XWINDOW (window) != it->w)
6751 continue;
6752
6753
6754
6755
6756 Lisp_Object invisible = Foverlay_get (overlay, Qinvisible);
6757 int invis = TEXT_PROP_MEANS_INVISIBLE (invisible);
6758
6759
6760 Lisp_Object str;
6761 if ((start == charpos || (end == charpos && invis != 0))
6762 && (str = Foverlay_get (overlay, Qbefore_string), STRINGP (str))
6763 && SCHARS (str))
6764 RECORD_OVERLAY_STRING (overlay, str, false);
6765
6766
6767 if ((end == charpos || (start == charpos && invis != 0))
6768 && (str = Foverlay_get (overlay, Qafter_string), STRINGP (str))
6769 && SCHARS (str))
6770 RECORD_OVERLAY_STRING (overlay, str, true);
6771 }
6772
6773 #undef RECORD_OVERLAY_STRING
6774
6775
6776 if (n > 1)
6777 qsort (entries, n, sizeof *entries, compare_overlay_entries);
6778
6779
6780 it->n_overlay_strings = n;
6781 it->overlay_strings_charpos = charpos;
6782
6783
6784
6785
6786 ptrdiff_t j = it->current.overlay_string_index;
6787 for (ptrdiff_t i = 0; i < OVERLAY_STRING_CHUNK_SIZE && j < n; i++, j++)
6788 {
6789 it->overlay_strings[i] = entries[j].string;
6790 it->string_overlays[i] = entries[j].overlay;
6791 }
6792
6793 CHECK_IT (it);
6794 SAFE_FREE ();
6795 }
6796
6797
6798
6799
6800
6801
6802 static bool
6803 get_overlay_strings_1 (struct it *it, ptrdiff_t charpos, bool compute_stop_p)
6804 {
6805
6806
6807
6808
6809
6810
6811
6812 it->current.overlay_string_index = 0;
6813 load_overlay_strings (it, charpos);
6814
6815
6816
6817
6818 if (it->n_overlay_strings)
6819 {
6820
6821
6822
6823 if (compute_stop_p)
6824 compute_stop_pos (it);
6825 eassert (it->face_id >= 0);
6826
6827
6828
6829 eassert (!compute_stop_p || it->sp == 0);
6830
6831
6832
6833
6834
6835
6836
6837
6838
6839 if (!(!it->bidi_p
6840 && STRINGP (it->string) && !SCHARS (it->string)))
6841 push_it (it, NULL);
6842
6843
6844
6845 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
6846 it->string = it->overlay_strings[0];
6847 it->from_overlay = Qnil;
6848 it->stop_charpos = 0;
6849 eassert (STRINGP (it->string));
6850 it->end_charpos = SCHARS (it->string);
6851 it->prev_stop = 0;
6852 it->base_level_stop = 0;
6853 it->multibyte_p = STRING_MULTIBYTE (it->string);
6854 it->method = GET_FROM_STRING;
6855 it->from_disp_prop_p = 0;
6856 it->cmp_it.id = -1;
6857
6858
6859
6860 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
6861 it->paragraph_embedding = it->bidi_it.paragraph_dir;
6862 else
6863 it->paragraph_embedding = L2R;
6864
6865
6866 if (it->bidi_p)
6867 {
6868 ptrdiff_t pos = (charpos > 0 ? charpos : IT_CHARPOS (*it));
6869
6870 it->bidi_it.string.lstring = it->string;
6871 it->bidi_it.string.s = NULL;
6872 it->bidi_it.string.schars = SCHARS (it->string);
6873 it->bidi_it.string.bufpos = pos;
6874 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
6875 it->bidi_it.string.unibyte = !it->multibyte_p;
6876 it->bidi_it.w = it->w;
6877 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
6878 }
6879 return true;
6880 }
6881
6882 it->current.overlay_string_index = -1;
6883 return false;
6884 }
6885
6886 static bool
6887 get_overlay_strings (struct it *it, ptrdiff_t charpos)
6888 {
6889 it->string = Qnil;
6890 it->method = GET_FROM_BUFFER;
6891
6892 get_overlay_strings_1 (it, charpos, true);
6893
6894 CHECK_IT (it);
6895
6896
6897 return STRINGP (it->string);
6898 }
6899
6900
6901
6902
6903
6904
6905
6906
6907
6908
6909
6910
6911
6912 static void
6913 push_it (struct it *it, struct text_pos *position)
6914 {
6915 struct iterator_stack_entry *p;
6916
6917 eassert (it->sp < IT_STACK_SIZE);
6918 p = it->stack + it->sp;
6919
6920 p->stop_charpos = it->stop_charpos;
6921 p->prev_stop = it->prev_stop;
6922 p->base_level_stop = it->base_level_stop;
6923 p->cmp_it = it->cmp_it;
6924 eassert (it->face_id >= 0);
6925 p->face_id = it->face_id;
6926 p->string = it->string;
6927 p->method = it->method;
6928 p->from_overlay = it->from_overlay;
6929 switch (p->method)
6930 {
6931 case GET_FROM_IMAGE:
6932 p->u.image.object = it->object;
6933 p->u.image.image_id = it->image_id;
6934 p->u.image.slice = it->slice;
6935 break;
6936 case GET_FROM_STRETCH:
6937 p->u.stretch.object = it->object;
6938 break;
6939 case GET_FROM_XWIDGET:
6940 p->u.xwidget.object = it->object;
6941 break;
6942 case GET_FROM_BUFFER:
6943 case GET_FROM_DISPLAY_VECTOR:
6944 case GET_FROM_STRING:
6945 case GET_FROM_C_STRING:
6946 break;
6947 default:
6948 emacs_abort ();
6949 }
6950 p->position = position ? *position : it->position;
6951 p->current = it->current;
6952 p->end_charpos = it->end_charpos;
6953 p->string_nchars = it->string_nchars;
6954 p->area = it->area;
6955 p->multibyte_p = it->multibyte_p;
6956 p->avoid_cursor_p = it->avoid_cursor_p;
6957 p->space_width = it->space_width;
6958 p->font_height = it->font_height;
6959 p->voffset = it->voffset;
6960 p->string_from_display_prop_p = it->string_from_display_prop_p;
6961 p->string_from_prefix_prop_p = it->string_from_prefix_prop_p;
6962 p->display_ellipsis_p = false;
6963 p->line_wrap = it->line_wrap;
6964 p->bidi_p = it->bidi_p;
6965 p->paragraph_embedding = it->paragraph_embedding;
6966 p->from_disp_prop_p = it->from_disp_prop_p;
6967 ++it->sp;
6968
6969
6970 if (it->bidi_p)
6971 bidi_push_it (&it->bidi_it);
6972 }
6973
6974 static void
6975 iterate_out_of_display_property (struct it *it)
6976 {
6977 bool buffer_p = !STRINGP (it->string);
6978 ptrdiff_t eob = (buffer_p ? ZV : it->end_charpos);
6979 ptrdiff_t bob = (buffer_p ? BEGV : 0);
6980
6981 eassert (eob >= CHARPOS (it->position) && CHARPOS (it->position) >= bob);
6982
6983
6984
6985
6986 if (it->bidi_it.first_elt && it->bidi_it.charpos < eob)
6987 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
6988
6989 while (it->bidi_it.charpos >= bob
6990 && it->prev_stop <= it->bidi_it.charpos
6991 && it->bidi_it.charpos < CHARPOS (it->position)
6992 && it->bidi_it.charpos < eob)
6993 bidi_move_to_visually_next (&it->bidi_it);
6994
6995
6996 if (it->bidi_it.charpos > CHARPOS (it->position))
6997 it->prev_stop = CHARPOS (it->position);
6998
6999
7000 if (it->bidi_it.charpos != CHARPOS (it->position))
7001 SET_TEXT_POS (it->position, it->bidi_it.charpos, it->bidi_it.bytepos);
7002 if (buffer_p)
7003 it->current.pos = it->position;
7004 else
7005 it->current.string_pos = it->position;
7006 }
7007
7008
7009
7010
7011
7012 static void
7013 restore_face_box_flags (struct it *it, int prev_face_id)
7014 {
7015 struct face *face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
7016
7017 if (face)
7018 {
7019 struct face *prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
7020
7021 if (!(it->start_of_box_run_p && prev_face && prev_face->box))
7022 it->start_of_box_run_p = (face->box != FACE_NO_BOX
7023 && (prev_face == NULL
7024 || prev_face->box == FACE_NO_BOX));
7025 it->face_box_p = face->box != FACE_NO_BOX;
7026 }
7027 }
7028
7029
7030
7031
7032
7033
7034
7035 static void
7036 pop_it (struct it *it)
7037 {
7038 struct iterator_stack_entry *p;
7039 bool from_display_prop = it->from_disp_prop_p;
7040 ptrdiff_t prev_pos = IT_CHARPOS (*it);
7041 int prev_face_id = it->face_id;
7042
7043 eassert (it->sp > 0);
7044 --it->sp;
7045 p = it->stack + it->sp;
7046 it->stop_charpos = p->stop_charpos;
7047 it->prev_stop = p->prev_stop;
7048 it->base_level_stop = p->base_level_stop;
7049 it->cmp_it = p->cmp_it;
7050 it->face_id = p->face_id;
7051 it->current = p->current;
7052 it->position = p->position;
7053 it->string = p->string;
7054 it->from_overlay = p->from_overlay;
7055 if (NILP (it->string))
7056 SET_TEXT_POS (it->current.string_pos, -1, -1);
7057 it->method = p->method;
7058 switch (it->method)
7059 {
7060 case GET_FROM_IMAGE:
7061 it->image_id = p->u.image.image_id;
7062 it->object = p->u.image.object;
7063 it->slice = p->u.image.slice;
7064 break;
7065 case GET_FROM_XWIDGET:
7066 it->object = p->u.xwidget.object;
7067 break;
7068 case GET_FROM_STRETCH:
7069 it->object = p->u.stretch.object;
7070 break;
7071 case GET_FROM_BUFFER:
7072 {
7073 restore_face_box_flags (it, prev_face_id);
7074 it->object = it->w->contents;
7075 }
7076 break;
7077 case GET_FROM_STRING:
7078 {
7079 restore_face_box_flags (it, prev_face_id);
7080 it->object = it->string;
7081 }
7082 break;
7083 case GET_FROM_DISPLAY_VECTOR:
7084 if (it->s)
7085 it->method = GET_FROM_C_STRING;
7086 else if (STRINGP (it->string))
7087 it->method = GET_FROM_STRING;
7088 else
7089 {
7090 it->method = GET_FROM_BUFFER;
7091 it->object = it->w->contents;
7092 }
7093 break;
7094 case GET_FROM_C_STRING:
7095 break;
7096 default:
7097 emacs_abort ();
7098 }
7099 it->end_charpos = p->end_charpos;
7100 it->string_nchars = p->string_nchars;
7101 it->area = p->area;
7102 it->multibyte_p = p->multibyte_p;
7103 it->avoid_cursor_p = p->avoid_cursor_p;
7104 it->space_width = p->space_width;
7105 it->font_height = p->font_height;
7106 it->voffset = p->voffset;
7107 it->string_from_display_prop_p = p->string_from_display_prop_p;
7108 it->string_from_prefix_prop_p = p->string_from_prefix_prop_p;
7109 it->line_wrap = p->line_wrap;
7110 it->bidi_p = p->bidi_p;
7111 it->paragraph_embedding = p->paragraph_embedding;
7112 it->from_disp_prop_p = p->from_disp_prop_p;
7113 if (it->bidi_p)
7114 {
7115 bidi_pop_it (&it->bidi_it);
7116
7117
7118
7119
7120
7121
7122
7123 if (from_display_prop
7124 && (it->method == GET_FROM_BUFFER || it->method == GET_FROM_STRING))
7125 iterate_out_of_display_property (it);
7126
7127 eassert ((BUFFERP (it->object)
7128 && IT_CHARPOS (*it) == it->bidi_it.charpos
7129 && IT_BYTEPOS (*it) == it->bidi_it.bytepos)
7130 || (STRINGP (it->object)
7131 && IT_STRING_CHARPOS (*it) == it->bidi_it.charpos
7132 && IT_STRING_BYTEPOS (*it) == it->bidi_it.bytepos)
7133 || (CONSP (it->object) && it->method == GET_FROM_STRETCH)
7134
7135
7136
7137
7138
7139
7140 || it->sp > 0);
7141 }
7142
7143
7144
7145 if (from_display_prop && it->sp == 0 && CHARPOS (it->position) != prev_pos)
7146 it->ignore_overlay_strings_at_pos_p = false;
7147 }
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157 static void
7158 back_to_previous_line_start (struct it *it)
7159 {
7160 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
7161
7162 dec_both (&cp, &bp);
7163 SET_WITH_NARROWED_BEGV (it, IT_CHARPOS (*it),
7164 find_newline_no_quit (cp, bp, -1, &IT_BYTEPOS (*it)),
7165 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
7166 }
7167
7168
7169
7170
7171
7172 static bool
7173 strings_with_newlines (ptrdiff_t startpos, ptrdiff_t endpos, struct window *w)
7174 {
7175 struct itree_node *node;
7176
7177 ITREE_FOREACH (node, current_buffer->overlays, startpos, endpos, DESCENDING)
7178 {
7179 Lisp_Object overlay = node->data;
7180 eassert (OVERLAYP (overlay));
7181
7182
7183 Lisp_Object window = Foverlay_get (overlay, Qwindow);
7184 if (WINDOWP (window) && XWINDOW (window) != w)
7185 continue;
7186
7187 ptrdiff_t ostart = node->begin;
7188 ptrdiff_t oend = node->end;
7189
7190
7191 if (!((startpos < oend && ostart < endpos)
7192 || (ostart == oend
7193 && (startpos == oend || (endpos == ZV && oend == endpos)))))
7194 continue;
7195
7196 Lisp_Object str;
7197 str = Foverlay_get (overlay, Qbefore_string);
7198 if (STRINGP (str) && SCHARS (str)
7199 && memchr (SDATA (str), '\n', SBYTES (str)))
7200 return true;
7201 str = Foverlay_get (overlay, Qafter_string);
7202 if (STRINGP (str) && SCHARS (str)
7203 && memchr (SDATA (str), '\n', SBYTES (str)))
7204 return true;
7205 }
7206
7207
7208 Lisp_Object cpos = make_fixnum (startpos);
7209 Lisp_Object limpos = make_fixnum (endpos);
7210
7211 while ((cpos = Fnext_single_property_change (cpos, Qdisplay, Qnil, limpos),
7212 !(NILP (cpos) || XFIXNAT (cpos) >= endpos)))
7213 {
7214 Lisp_Object spec = Fget_char_property (cpos, Qdisplay, Qnil);
7215 Lisp_Object string = string_from_display_spec (spec);
7216 if (STRINGP (string)
7217 && memchr (SDATA (string), '\n', SBYTES (string)))
7218 return true;
7219 }
7220
7221 return false;
7222 }
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246 static bool
7247 forward_to_next_line_start (struct it *it, bool *skipped_p,
7248 struct bidi_it *bidi_it_prev)
7249 {
7250 ptrdiff_t old_selective;
7251 bool newline_found_p = false;
7252 int n;
7253 const int MAX_NEWLINE_DISTANCE = 500;
7254
7255
7256
7257 if (it->what == IT_CHARACTER
7258 && it->c == '\n'
7259 && CHARPOS (it->position) == IT_CHARPOS (*it))
7260 {
7261 if (it->bidi_p && bidi_it_prev)
7262 *bidi_it_prev = it->bidi_it;
7263 set_iterator_to_next (it, false);
7264 it->c = 0;
7265 return true;
7266 }
7267
7268
7269
7270
7271
7272 old_selective = it->selective;
7273 it->selective = 0;
7274
7275
7276
7277
7278 for (n = 0;
7279 !newline_found_p && n < MAX_NEWLINE_DISTANCE;
7280 n += !STRINGP (it->string))
7281 {
7282 if (!get_next_display_element (it))
7283 return false;
7284 newline_found_p = it->what == IT_CHARACTER && it->c == '\n';
7285 if (newline_found_p && it->bidi_p && bidi_it_prev)
7286 *bidi_it_prev = it->bidi_it;
7287 set_iterator_to_next (it, false);
7288 }
7289
7290
7291
7292 if (!newline_found_p)
7293 {
7294 ptrdiff_t bytepos, start = IT_CHARPOS (*it);
7295 ptrdiff_t limit = find_newline_no_quit (start, IT_BYTEPOS (*it),
7296 1, &bytepos);
7297 eassert (!STRINGP (it->string));
7298
7299
7300
7301
7302 bool no_strings_with_newlines = it->stop_charpos >= limit;
7303
7304 if (!no_strings_with_newlines)
7305 {
7306 if (!(current_buffer->long_line_optimizations_p
7307 && it->line_wrap == TRUNCATE))
7308 {
7309
7310
7311 Lisp_Object pos =
7312 Fnext_single_property_change (make_fixnum (start),
7313 Qdisplay, Qnil,
7314 make_fixnum (limit));
7315 no_strings_with_newlines =
7316 (NILP (pos) || XFIXNAT (pos) == limit)
7317 && next_overlay_change (start) == ZV;
7318 }
7319 else
7320 {
7321
7322
7323
7324
7325 no_strings_with_newlines =
7326 !strings_with_newlines (start, limit, it->w);
7327 }
7328 }
7329
7330
7331
7332
7333 if (no_strings_with_newlines)
7334 {
7335 if (!it->bidi_p || !bidi_it_prev)
7336 {
7337
7338 IT_CHARPOS (*it) = limit;
7339 IT_BYTEPOS (*it) = bytepos;
7340 }
7341 else
7342 {
7343
7344
7345
7346 struct bidi_it bprev;
7347
7348
7349
7350
7351 if (it->bidi_it.disp_pos < limit)
7352 {
7353 it->bidi_it.disp_pos = limit;
7354 it->bidi_it.disp_prop = 0;
7355 }
7356 do {
7357 bprev = it->bidi_it;
7358 bidi_move_to_visually_next (&it->bidi_it);
7359 } while (it->bidi_it.charpos != limit);
7360 IT_CHARPOS (*it) = limit;
7361 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7362 if (bidi_it_prev)
7363 *bidi_it_prev = bprev;
7364 }
7365 *skipped_p = newline_found_p = true;
7366 }
7367 else
7368 {
7369
7370 while (!newline_found_p)
7371 {
7372 if (!get_next_display_element (it))
7373 break;
7374 newline_found_p = ITERATOR_AT_END_OF_LINE_P (it);
7375 if (newline_found_p && it->bidi_p && bidi_it_prev)
7376 *bidi_it_prev = it->bidi_it;
7377 set_iterator_to_next (it, false);
7378 }
7379 }
7380 }
7381
7382 it->selective = old_selective;
7383 return newline_found_p;
7384 }
7385
7386
7387
7388
7389
7390
7391
7392 static void
7393 back_to_previous_visible_line_start (struct it *it)
7394 {
7395 while (IT_CHARPOS (*it) > BEGV)
7396 {
7397 back_to_previous_line_start (it);
7398
7399 if (IT_CHARPOS (*it) <= BEGV)
7400 break;
7401
7402
7403
7404 if (it->selective > 0
7405 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7406 it->selective))
7407 continue;
7408
7409
7410 {
7411 Lisp_Object prop;
7412 prop = Fget_char_property (make_fixnum (IT_CHARPOS (*it) - 1),
7413 Qinvisible, it->window);
7414 if (TEXT_PROP_MEANS_INVISIBLE (prop) != 0)
7415 continue;
7416 }
7417
7418 if (IT_CHARPOS (*it) <= BEGV)
7419 break;
7420
7421 {
7422 struct it it2;
7423 void *it2data = NULL;
7424 ptrdiff_t pos;
7425 ptrdiff_t beg, end;
7426 Lisp_Object val, overlay;
7427
7428 SAVE_IT (it2, *it, it2data);
7429
7430
7431 if (find_composition (IT_CHARPOS (*it), -1, &beg, &end, &val, Qnil)
7432 && beg < IT_CHARPOS (*it))
7433 goto replaced;
7434
7435
7436
7437 pos = --IT_CHARPOS (it2);
7438 --IT_BYTEPOS (it2);
7439 it2.sp = 0;
7440 bidi_unshelve_cache (NULL, false);
7441 it2.string_from_display_prop_p = false;
7442 it2.from_disp_prop_p = false;
7443 if (handle_display_prop (&it2) == HANDLED_RETURN
7444 && !NILP (val = get_char_property_and_overlay
7445 (make_fixnum (pos), Qdisplay, Qnil, &overlay))
7446 && (OVERLAYP (overlay)
7447 ? (beg = OVERLAY_START (overlay))
7448 : get_property_and_range (pos, Qdisplay, &val, &beg, &end, Qnil)))
7449 {
7450 RESTORE_IT (it, it, it2data);
7451 goto replaced;
7452 }
7453
7454
7455 RESTORE_IT (it, it, it2data);
7456 break;
7457
7458 replaced:
7459 if (beg < BEGV)
7460 beg = BEGV;
7461 IT_CHARPOS (*it) = beg;
7462 IT_BYTEPOS (*it) = buf_charpos_to_bytepos (current_buffer, beg);
7463 }
7464 }
7465
7466 it->continuation_lines_width = 0;
7467
7468 eassert (IT_CHARPOS (*it) >= BEGV);
7469 eassert (it->medium_narrowing_begv > 0
7470 || IT_CHARPOS (*it) == BEGV
7471 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7472 CHECK_IT (it);
7473 }
7474
7475
7476
7477
7478
7479
7480
7481 void
7482 reseat_at_previous_visible_line_start (struct it *it)
7483 {
7484 back_to_previous_visible_line_start (it);
7485 reseat (it, it->current.pos, true);
7486 CHECK_IT (it);
7487 }
7488
7489
7490
7491
7492
7493
7494
7495
7496
7497 static void
7498 reseat_at_next_visible_line_start (struct it *it, bool on_newline_p)
7499 {
7500 bool skipped_p = false;
7501 struct bidi_it bidi_it_prev;
7502 bool newline_found_p
7503 = forward_to_next_line_start (it, &skipped_p,
7504 on_newline_p ? &bidi_it_prev : NULL);
7505
7506
7507
7508 if (it->selective > 0)
7509 while (IT_CHARPOS (*it) < ZV
7510 && indented_beyond_p (IT_CHARPOS (*it), IT_BYTEPOS (*it),
7511 it->selective))
7512 {
7513 eassert (IT_BYTEPOS (*it) == BEGV
7514 || FETCH_BYTE (IT_BYTEPOS (*it) - 1) == '\n');
7515 newline_found_p =
7516 forward_to_next_line_start (it, &skipped_p,
7517 on_newline_p ? &bidi_it_prev : NULL);
7518 }
7519
7520
7521 if (on_newline_p && newline_found_p)
7522 {
7523 if (STRINGP (it->string))
7524 {
7525 if (IT_STRING_CHARPOS (*it) > 0)
7526 {
7527 if (!it->bidi_p)
7528 {
7529 --IT_STRING_CHARPOS (*it);
7530 --IT_STRING_BYTEPOS (*it);
7531 }
7532 else
7533 {
7534
7535
7536
7537 it->bidi_it = bidi_it_prev;
7538 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
7539 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
7540 }
7541 }
7542 }
7543 else if (IT_CHARPOS (*it) > BEGV)
7544 {
7545 if (!it->bidi_p)
7546 {
7547 --IT_CHARPOS (*it);
7548 --IT_BYTEPOS (*it);
7549 }
7550 else
7551 {
7552
7553
7554 it->bidi_it = bidi_it_prev;
7555 IT_CHARPOS (*it) = it->bidi_it.charpos;
7556 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
7557 }
7558 reseat (it, it->current.pos, false);
7559 }
7560 }
7561 else if (skipped_p)
7562 reseat (it, it->current.pos, false);
7563
7564 CHECK_IT (it);
7565 }
7566
7567
7568
7569
7570
7571
7572
7573
7574
7575
7576
7577
7578 static void
7579 reseat (struct it *it, struct text_pos pos, bool force_p)
7580 {
7581 ptrdiff_t original_pos = IT_CHARPOS (*it);
7582
7583 reseat_1 (it, pos, false);
7584
7585 if (current_buffer->long_line_optimizations_p)
7586 {
7587 if (!it->medium_narrowing_begv)
7588 {
7589 it->medium_narrowing_begv
7590 = get_medium_narrowing_begv (it->w, window_point (it->w));
7591 it->medium_narrowing_zv
7592 = get_medium_narrowing_zv (it->w, window_point (it->w));
7593 it->large_narrowing_begv
7594 = get_large_narrowing_begv (window_point (it->w));
7595 it->large_narrowing_zv
7596 = get_large_narrowing_zv (window_point (it->w));
7597 }
7598 else if ((pos.charpos < it->medium_narrowing_begv
7599 || pos.charpos > it->medium_narrowing_zv)
7600 && (!redisplaying_p || it->line_wrap == TRUNCATE))
7601 {
7602 it->medium_narrowing_begv
7603 = get_medium_narrowing_begv (it->w, pos.charpos);
7604 it->medium_narrowing_zv
7605 = get_medium_narrowing_zv (it->w, pos.charpos);
7606 it->large_narrowing_begv
7607 = get_large_narrowing_begv (window_point (it->w));
7608 it->large_narrowing_zv
7609 = get_large_narrowing_zv (window_point (it->w));
7610 }
7611 }
7612
7613
7614
7615 if (force_p
7616 || CHARPOS (pos) > it->stop_charpos
7617 || CHARPOS (pos) < original_pos)
7618 {
7619 if (it->bidi_p)
7620 {
7621
7622
7623
7624
7625
7626
7627
7628
7629
7630
7631 if (CHARPOS (pos) != it->prev_stop)
7632 it->prev_stop = CHARPOS (pos);
7633 if (CHARPOS (pos) < it->base_level_stop)
7634 it->base_level_stop = 0;
7635 handle_stop (it);
7636 }
7637 else
7638 {
7639 handle_stop (it);
7640 it->prev_stop = it->base_level_stop = 0;
7641 }
7642
7643 }
7644
7645 CHECK_IT (it);
7646 }
7647
7648
7649
7650
7651
7652 static void
7653 reseat_1 (struct it *it, struct text_pos pos, bool set_stop_p)
7654 {
7655
7656 eassert (it->s == NULL);
7657
7658
7659 eassert (CHARPOS (pos) >= BEGV && CHARPOS (pos) <= ZV);
7660
7661 it->current.pos = it->position = pos;
7662 it->end_charpos = ZV;
7663 it->dpvec = NULL;
7664 it->current.dpvec_index = -1;
7665 it->current.overlay_string_index = -1;
7666 IT_STRING_CHARPOS (*it) = -1;
7667 IT_STRING_BYTEPOS (*it) = -1;
7668 it->string = Qnil;
7669 it->method = GET_FROM_BUFFER;
7670 it->object = it->w->contents;
7671 it->area = TEXT_AREA;
7672 it->multibyte_p = !NILP (BVAR (current_buffer, enable_multibyte_characters));
7673 it->sp = 0;
7674 it->string_from_display_prop_p = false;
7675 it->string_from_prefix_prop_p = false;
7676
7677 it->from_disp_prop_p = false;
7678 it->face_before_selective_p = false;
7679 if (it->bidi_p)
7680 {
7681 bidi_init_it (IT_CHARPOS (*it), IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7682 &it->bidi_it);
7683 bidi_unshelve_cache (NULL, false);
7684 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7685 it->bidi_it.string.s = NULL;
7686 it->bidi_it.string.lstring = Qnil;
7687 it->bidi_it.string.bufpos = 0;
7688 it->bidi_it.string.from_disp_str = false;
7689 it->bidi_it.string.unibyte = false;
7690 it->bidi_it.w = it->w;
7691 }
7692
7693 if (set_stop_p)
7694 {
7695 it->stop_charpos = CHARPOS (pos);
7696 it->base_level_stop = CHARPOS (pos);
7697 }
7698
7699 it->cmp_it.id = -1;
7700 it->min_width_property = Qnil;
7701 }
7702
7703
7704
7705
7706
7707
7708
7709
7710
7711
7712
7713
7714
7715
7716
7717
7718
7719
7720
7721
7722 static void
7723 reseat_to_string (struct it *it, const char *s, Lisp_Object string,
7724 ptrdiff_t charpos, ptrdiff_t precision, int field_width,
7725 int multibyte)
7726 {
7727
7728 it->stop_charpos = -1;
7729
7730
7731 memset (&it->current, 0, sizeof it->current);
7732 it->current.overlay_string_index = -1;
7733 it->current.dpvec_index = -1;
7734 eassert (charpos >= 0);
7735
7736
7737
7738 if (multibyte >= 0)
7739 it->multibyte_p = multibyte > 0;
7740
7741
7742
7743
7744
7745 it->bidi_p =
7746 !redisplay__inhibit_bidi
7747 && !NILP (BVAR (&buffer_defaults, bidi_display_reordering));
7748
7749 if (s == NULL)
7750 {
7751 eassert (STRINGP (string));
7752 it->string = string;
7753 it->s = NULL;
7754 it->end_charpos = it->string_nchars = SCHARS (string);
7755 it->method = GET_FROM_STRING;
7756 it->current.string_pos = string_pos (charpos, string);
7757
7758 if (it->bidi_p)
7759 {
7760 it->bidi_it.string.lstring = string;
7761 it->bidi_it.string.s = NULL;
7762 it->bidi_it.string.schars = it->end_charpos;
7763 it->bidi_it.string.bufpos = 0;
7764 it->bidi_it.string.from_disp_str = false;
7765 it->bidi_it.string.unibyte = !it->multibyte_p;
7766 it->bidi_it.w = it->w;
7767 bidi_init_it (charpos, IT_STRING_BYTEPOS (*it),
7768 FRAME_WINDOW_P (it->f), &it->bidi_it);
7769 }
7770 }
7771 else
7772 {
7773 it->s = (const unsigned char *) s;
7774 it->string = Qnil;
7775
7776
7777
7778 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = -1;
7779 if (it->multibyte_p)
7780 {
7781 it->current.pos = c_string_pos (charpos, s, true);
7782 it->end_charpos = it->string_nchars = number_of_chars (s, true);
7783 }
7784 else
7785 {
7786 IT_CHARPOS (*it) = IT_BYTEPOS (*it) = charpos;
7787 it->end_charpos = it->string_nchars = strlen (s);
7788 }
7789
7790 if (it->bidi_p)
7791 {
7792 it->bidi_it.string.lstring = Qnil;
7793 it->bidi_it.string.s = (const unsigned char *) s;
7794 it->bidi_it.string.schars = it->end_charpos;
7795 it->bidi_it.string.bufpos = 0;
7796 it->bidi_it.string.from_disp_str = false;
7797 it->bidi_it.string.unibyte = !it->multibyte_p;
7798 it->bidi_it.w = it->w;
7799 bidi_init_it (charpos, IT_BYTEPOS (*it), FRAME_WINDOW_P (it->f),
7800 &it->bidi_it);
7801 }
7802 it->method = GET_FROM_C_STRING;
7803 }
7804
7805
7806
7807 if (precision > 0 && it->end_charpos - charpos > precision)
7808 {
7809 it->end_charpos = it->string_nchars = charpos + precision;
7810 if (it->bidi_p)
7811 it->bidi_it.string.schars = it->end_charpos;
7812 }
7813
7814
7815
7816
7817
7818 if (field_width < 0)
7819 field_width = DISP_INFINITY;
7820
7821
7822
7823 if (field_width > it->end_charpos - charpos)
7824 it->end_charpos = charpos + field_width;
7825
7826
7827 if (DISP_TABLE_P (Vstandard_display_table))
7828 it->dp = XCHAR_TABLE (Vstandard_display_table);
7829
7830 it->stop_charpos = charpos;
7831 it->prev_stop = charpos;
7832 it->base_level_stop = 0;
7833 if (it->bidi_p)
7834 {
7835 it->bidi_it.first_elt = true;
7836 it->bidi_it.paragraph_dir = NEUTRAL_DIR;
7837 it->bidi_it.disp_pos = -1;
7838 }
7839 if (s == NULL && it->multibyte_p)
7840 {
7841 ptrdiff_t endpos = SCHARS (it->string);
7842 if (endpos > it->end_charpos)
7843 endpos = it->end_charpos;
7844 composition_compute_stop_pos (&it->cmp_it, charpos, -1, endpos,
7845 it->string);
7846 }
7847 CHECK_IT (it);
7848 }
7849
7850
7851
7852
7853
7854
7855
7856
7857
7858 typedef bool (*next_element_function) (struct it *);
7859
7860 static next_element_function const get_next_element[NUM_IT_METHODS] =
7861 {
7862 next_element_from_buffer,
7863 next_element_from_display_vector,
7864 next_element_from_string,
7865 next_element_from_c_string,
7866 next_element_from_image,
7867 next_element_from_stretch,
7868 next_element_from_xwidget,
7869 };
7870
7871 #define GET_NEXT_DISPLAY_ELEMENT(it) (*get_next_element[(it)->method]) (it)
7872
7873
7874
7875
7876
7877
7878
7879
7880
7881
7882 #define CHAR_COMPOSED_P(IT,CHARPOS,BYTEPOS,END_CHARPOS) \
7883 ((IT)->cmp_it.id >= 0 \
7884 || ((IT)->cmp_it.stop_pos == (CHARPOS) \
7885 && composition_reseat_it (&(IT)->cmp_it, CHARPOS, BYTEPOS, \
7886 END_CHARPOS, (IT)->w, \
7887 (IT)->bidi_p \
7888 ? (IT)->bidi_it.resolved_level \
7889 : -1, \
7890 FACE_FROM_ID_OR_NULL ((IT)->f, \
7891 (IT)->face_id), \
7892 (IT)->string)))
7893
7894
7895
7896
7897
7898
7899
7900
7901
7902 Lisp_Object
7903 lookup_glyphless_char_display (int c, struct it *it)
7904 {
7905 Lisp_Object glyphless_method = Qnil;
7906
7907 if (CHAR_TABLE_P (Vglyphless_char_display)
7908 && CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display)) >= 1)
7909 {
7910 if (c >= 0)
7911 glyphless_method = CHAR_TABLE_REF (Vglyphless_char_display, c);
7912 else
7913 glyphless_method = XCHAR_TABLE (Vglyphless_char_display)->extras[0];
7914
7915 if (CONSP (glyphless_method))
7916 glyphless_method = FRAME_WINDOW_P (it->f)
7917 ? XCAR (glyphless_method)
7918 : XCDR (glyphless_method);
7919 }
7920
7921 retry:
7922 if (NILP (glyphless_method))
7923 {
7924 if (c >= 0)
7925
7926 return Qnil;
7927
7928 glyphless_method = Qempty_box;
7929 }
7930 if (EQ (glyphless_method, Qzero_width))
7931 {
7932 if (c >= 0)
7933 return glyphless_method;
7934
7935 glyphless_method = Qempty_box;
7936 }
7937 if (EQ (glyphless_method, Qthin_space))
7938 it->glyphless_method = GLYPHLESS_DISPLAY_THIN_SPACE;
7939 else if (EQ (glyphless_method, Qempty_box))
7940 it->glyphless_method = GLYPHLESS_DISPLAY_EMPTY_BOX;
7941 else if (EQ (glyphless_method, Qhex_code))
7942 it->glyphless_method = GLYPHLESS_DISPLAY_HEX_CODE;
7943 else if (STRINGP (glyphless_method))
7944 it->glyphless_method = GLYPHLESS_DISPLAY_ACRONYM;
7945 else
7946 {
7947
7948 glyphless_method = Qnil;
7949 goto retry;
7950 }
7951 it->what = IT_GLYPHLESS;
7952 return glyphless_method;
7953 }
7954
7955
7956
7957 static struct frame *last_escape_glyph_frame = NULL;
7958 static int last_escape_glyph_face_id = (1 << FACE_ID_BITS);
7959 static int last_escape_glyph_merged_face_id = 0;
7960
7961 static int
7962 merge_escape_glyph_face (struct it *it)
7963 {
7964 int face_id;
7965
7966 if (it->f == last_escape_glyph_frame
7967 && it->face_id == last_escape_glyph_face_id)
7968 face_id = last_escape_glyph_merged_face_id;
7969 else
7970 {
7971
7972 face_id = merge_faces (it->w, Qescape_glyph, 0, it->face_id);
7973 last_escape_glyph_frame = it->f;
7974 last_escape_glyph_face_id = it->face_id;
7975 last_escape_glyph_merged_face_id = face_id;
7976 }
7977 return face_id;
7978 }
7979
7980
7981
7982 static struct frame *last_glyphless_glyph_frame = NULL;
7983 static int last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
7984 static int last_glyphless_glyph_merged_face_id = 0;
7985
7986 int
7987 merge_glyphless_glyph_face (struct it *it)
7988 {
7989 int face_id;
7990
7991 if (it->f == last_glyphless_glyph_frame
7992 && it->face_id == last_glyphless_glyph_face_id)
7993 face_id = last_glyphless_glyph_merged_face_id;
7994 else
7995 {
7996
7997 face_id = merge_faces (it->w, Qglyphless_char, 0, it->face_id);
7998 last_glyphless_glyph_frame = it->f;
7999 last_glyphless_glyph_face_id = it->face_id;
8000 last_glyphless_glyph_merged_face_id = face_id;
8001 }
8002 return face_id;
8003 }
8004
8005
8006
8007
8008 void
8009 forget_escape_and_glyphless_faces (void)
8010 {
8011 last_escape_glyph_frame = NULL;
8012 last_escape_glyph_face_id = (1 << FACE_ID_BITS);
8013 last_glyphless_glyph_frame = NULL;
8014 last_glyphless_glyph_face_id = (1 << FACE_ID_BITS);
8015 }
8016
8017
8018
8019
8020
8021 static bool
8022 get_next_display_element (struct it *it)
8023 {
8024
8025
8026
8027
8028 bool success_p;
8029
8030 get_next:
8031 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
8032
8033 if (it->what == IT_CHARACTER)
8034 {
8035
8036
8037
8038
8039
8040 if (it->bidi_p && it->bidi_it.type == STRONG_R
8041 && !inhibit_bidi_mirroring)
8042 it->c = bidi_mirror_char (it->c);
8043
8044
8045
8046
8047
8048
8049
8050
8051
8052 if (success_p && it->dpvec == NULL)
8053 {
8054 Lisp_Object dv;
8055 struct charset *unibyte = CHARSET_FROM_ID (charset_unibyte);
8056 bool nonascii_space_p = false;
8057 bool nonascii_hyphen_p = false;
8058 int c = it->c;
8059
8060 if (! it->multibyte_p && ! ASCII_CHAR_P (c))
8061 {
8062 eassert (SINGLE_BYTE_CHAR_P (c));
8063 if (unibyte_display_via_language_environment)
8064 {
8065 c = DECODE_CHAR (unibyte, c);
8066 if (c < 0)
8067 c = BYTE8_TO_CHAR (it->c);
8068 }
8069 else
8070 c = BYTE8_TO_CHAR (it->c);
8071 }
8072
8073 if (it->dp
8074 && (dv = DISP_CHAR_VECTOR (it->dp, c),
8075 VECTORP (dv)))
8076 {
8077 struct Lisp_Vector *v = XVECTOR (dv);
8078
8079
8080
8081
8082 if (v->header.size)
8083 {
8084 it->dpvec_char_len = it->len;
8085 it->dpvec = v->contents;
8086 it->dpend = v->contents + v->header.size;
8087 it->current.dpvec_index = 0;
8088 it->dpvec_face_id = -1;
8089 it->saved_face_id = it->face_id;
8090 it->method = GET_FROM_DISPLAY_VECTOR;
8091 it->ellipsis_p = false;
8092 }
8093 else
8094 {
8095 set_iterator_to_next (it, false);
8096 }
8097 goto get_next;
8098 }
8099
8100 if (! NILP (lookup_glyphless_char_display (c, it)))
8101 {
8102 if (it->what == IT_GLYPHLESS)
8103 goto done;
8104
8105 set_iterator_to_next (it, false);
8106 goto get_next;
8107 }
8108
8109
8110
8111 if (! ASCII_CHAR_P (c) && ! NILP (Vnobreak_char_display))
8112 {
8113 if (blankp (c))
8114 nonascii_space_p = true;
8115 else if (c == SOFT_HYPHEN || c == HYPHEN
8116 || c == NON_BREAKING_HYPHEN)
8117 nonascii_hyphen_p = true;
8118 }
8119
8120
8121
8122
8123
8124
8125
8126
8127
8128
8129
8130
8131 if (((c < ' ' || c == 127)
8132 ? (it->area != TEXT_AREA
8133
8134 || (c != '\t'
8135 && it->glyph_row
8136 && (it->glyph_row->mode_line_p || it->avoid_cursor_p))
8137 || (c != '\n' && c != '\t'))
8138 : (nonascii_space_p
8139 || nonascii_hyphen_p
8140 || CHAR_BYTE8_P (c)
8141 || ! CHAR_PRINTABLE_P (c))))
8142 {
8143
8144
8145
8146
8147
8148
8149 Lisp_Object gc;
8150 int ctl_len;
8151 int face_id;
8152 int lface_id = 0;
8153 int escape_glyph;
8154
8155
8156
8157 if (ASCII_CHAR_P (c) && it->ctl_arrow_p)
8158 {
8159 int g;
8160
8161 g = '^';
8162
8163 if (it->dp
8164 && (gc = DISP_CTRL_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8165 {
8166 g = GLYPH_CODE_CHAR (gc);
8167 lface_id = GLYPH_CODE_FACE (gc);
8168 }
8169
8170 face_id = (lface_id
8171 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8172 : merge_escape_glyph_face (it));
8173
8174 XSETINT (it->ctl_chars[0], g);
8175 XSETINT (it->ctl_chars[1], c ^ 0100);
8176 ctl_len = 2;
8177 goto display_control;
8178 }
8179
8180
8181
8182
8183 if (nonascii_space_p && EQ (Vnobreak_char_display, Qt))
8184 {
8185
8186 face_id = merge_faces (it->w, Qnobreak_space, 0,
8187 it->face_id);
8188 XSETINT (it->ctl_chars[0],
8189 nobreak_char_ascii_display ? ' ' : it->c);
8190 ctl_len = 1;
8191 goto display_control;
8192 }
8193
8194
8195
8196
8197 if (nonascii_hyphen_p && EQ (Vnobreak_char_display, Qt))
8198 {
8199
8200 face_id = merge_faces (it->w, Qnobreak_hyphen, 0,
8201 it->face_id);
8202 XSETINT (it->ctl_chars[0],
8203 nobreak_char_ascii_display ? '-' : it->c);
8204 ctl_len = 1;
8205 goto display_control;
8206 }
8207
8208
8209
8210
8211 escape_glyph = '\\';
8212
8213 if (it->dp
8214 && (gc = DISP_ESCAPE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
8215 {
8216 escape_glyph = GLYPH_CODE_CHAR (gc);
8217 lface_id = GLYPH_CODE_FACE (gc);
8218 }
8219
8220 face_id = (lface_id
8221 ? merge_faces (it->w, Qt, lface_id, it->face_id)
8222 : merge_escape_glyph_face (it));
8223
8224
8225
8226 if (nonascii_space_p || nonascii_hyphen_p)
8227 {
8228 XSETINT (it->ctl_chars[0], escape_glyph);
8229 XSETINT (it->ctl_chars[1], nonascii_space_p ? ' ' : '-');
8230 ctl_len = 2;
8231 goto display_control;
8232 }
8233
8234 {
8235 char str[10];
8236 int len, i;
8237
8238 if (CHAR_BYTE8_P (c))
8239
8240 c = CHAR_TO_BYTE8 (c);
8241 const char *format_string = display_raw_bytes_as_hex
8242 ? "x%02x"
8243 : "%03o";
8244 len = sprintf (str, format_string, c + 0u);
8245
8246 XSETINT (it->ctl_chars[0], escape_glyph);
8247 for (i = 0; i < len; i++)
8248 XSETINT (it->ctl_chars[i + 1], str[i]);
8249 ctl_len = len + 1;
8250 }
8251
8252 display_control:
8253
8254 it->dpvec_char_len = it->len;
8255 it->dpvec = it->ctl_chars;
8256 it->dpend = it->dpvec + ctl_len;
8257 it->current.dpvec_index = 0;
8258 it->dpvec_face_id = face_id;
8259 it->saved_face_id = it->face_id;
8260 it->method = GET_FROM_DISPLAY_VECTOR;
8261 it->ellipsis_p = false;
8262 goto get_next;
8263 }
8264 it->char_to_display = c;
8265 }
8266 else if (success_p)
8267 {
8268 it->char_to_display = it->c;
8269 }
8270 }
8271
8272 #ifdef HAVE_WINDOW_SYSTEM
8273
8274
8275 if ((it->what == IT_CHARACTER || it->what == IT_COMPOSITION)
8276 && it->multibyte_p
8277 && success_p
8278 && FRAME_WINDOW_P (it->f))
8279 {
8280 struct face *face = FACE_FROM_ID (it->f, it->face_id);
8281
8282 if (it->what == IT_COMPOSITION && it->cmp_it.ch >= 0)
8283 {
8284
8285 Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
8286
8287 it->face_id = face_for_font (it->f, LGSTRING_FONT (gstring), face);
8288 }
8289 else
8290 {
8291 ptrdiff_t pos = (it->s ? -1
8292 : STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
8293 : IT_CHARPOS (*it));
8294 int c;
8295
8296 if (it->what == IT_CHARACTER)
8297 c = it->char_to_display;
8298 else
8299 {
8300 struct composition *cmp = composition_table[it->cmp_it.id];
8301 int i;
8302
8303 c = ' ';
8304 for (i = 0; i < cmp->glyph_len; i++)
8305
8306
8307 if ((c = COMPOSITION_GLYPH (cmp, i)) != '\t')
8308 break;
8309 }
8310 it->face_id = FACE_FOR_CHAR (it->f, face, c, pos, it->string);
8311 }
8312 }
8313 #endif
8314
8315 done:
8316
8317
8318 if (it->face_box_p
8319 && it->s == NULL)
8320 {
8321 if (it->method == GET_FROM_STRING && it->sp)
8322 {
8323 int face_id = underlying_face_id (it);
8324 struct face *face = FACE_FROM_ID_OR_NULL (it->f, face_id);
8325
8326 if (face)
8327 {
8328 if (face->box == FACE_NO_BOX)
8329 {
8330
8331
8332 int string_face_id = face_after_it_pos (it);
8333 if (FACE_FROM_ID (it->f, string_face_id)->box == FACE_NO_BOX)
8334 it->end_of_box_run_p = true;
8335 }
8336
8337
8338
8339 else if (((IT_STRING_CHARPOS (*it) >= SCHARS (it->string) - 1)
8340
8341
8342
8343 || (it->what == IT_COMPOSITION
8344 && (IT_STRING_CHARPOS (*it) + it->cmp_it.nchars
8345 >= SCHARS (it->string))))
8346
8347
8348 && ((it->current.overlay_string_index >= 0
8349 && (it->current.overlay_string_index
8350 == it->n_overlay_strings - 1))
8351
8352 || it->from_disp_prop_p))
8353 {
8354 ptrdiff_t ignore;
8355 int next_face_id;
8356 bool text_from_string = false;
8357
8358
8359 struct text_pos pos = it->current.pos;
8360
8361
8362
8363
8364
8365
8366
8367
8368
8369
8370
8371 if (it->from_disp_prop_p)
8372 {
8373 int stackp = it->sp - 1;
8374
8375
8376 while (stackp >= 0
8377 && STRINGP ((it->stack + stackp)->string))
8378 stackp--;
8379 if (stackp < 0)
8380 {
8381
8382
8383
8384
8385
8386
8387 text_from_string = true;
8388 pos = it->stack[it->sp - 1].position;
8389 }
8390 else
8391 pos = (it->stack + stackp)->position;
8392 }
8393 else
8394 INC_TEXT_POS (pos, it->multibyte_p);
8395
8396 if (text_from_string)
8397 {
8398 Lisp_Object base_string = it->stack[it->sp - 1].string;
8399
8400 if (CHARPOS (pos) >= SCHARS (base_string) - 1)
8401 it->end_of_box_run_p = true;
8402 else
8403 {
8404 next_face_id
8405 = face_at_string_position (it->w, base_string,
8406 CHARPOS (pos), 0,
8407 &ignore, face_id,
8408 false, 0);
8409 if (FACE_FROM_ID (it->f, next_face_id)->box
8410 == FACE_NO_BOX)
8411 it->end_of_box_run_p = true;
8412 }
8413 }
8414 else if (CHARPOS (pos) >= ZV)
8415 it->end_of_box_run_p = true;
8416 else
8417 {
8418 next_face_id =
8419 face_at_buffer_position (it->w, CHARPOS (pos),
8420 &ignore,
8421 CHARPOS (pos)
8422 + TEXT_PROP_DISTANCE_LIMIT,
8423 false, -1, 0);
8424 if (FACE_FROM_ID (it->f, next_face_id)->box
8425 == FACE_NO_BOX)
8426 it->end_of_box_run_p = true;
8427 }
8428 }
8429 }
8430 }
8431
8432
8433 else if (it->method != GET_FROM_DISPLAY_VECTOR)
8434 {
8435 int face_id = face_after_it_pos (it);
8436 if (face_id != it->face_id
8437 && FACE_FROM_ID (it->f, face_id)->box == FACE_NO_BOX)
8438 it->end_of_box_run_p = true;
8439 }
8440 }
8441
8442
8443
8444
8445
8446 if (!success_p && it->sp > 0)
8447 {
8448 set_iterator_to_next (it, false);
8449 success_p = get_next_display_element (it);
8450 }
8451
8452
8453 return success_p;
8454 }
8455
8456
8457
8458
8459
8460
8461
8462
8463
8464
8465
8466
8467
8468
8469
8470
8471
8472 void
8473 set_iterator_to_next (struct it *it, bool reseat_p)
8474 {
8475
8476 if (max_redisplay_ticks > 0)
8477 update_redisplay_ticks (1, it->w);
8478
8479 switch (it->method)
8480 {
8481 case GET_FROM_BUFFER:
8482
8483
8484
8485 if (ITERATOR_AT_END_OF_LINE_P (it) && reseat_p)
8486 reseat_at_next_visible_line_start (it, false);
8487 else if (it->cmp_it.id >= 0)
8488 {
8489
8490 if (! it->bidi_p)
8491 {
8492 IT_CHARPOS (*it) += it->cmp_it.nchars;
8493 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
8494 }
8495 else
8496 {
8497 int i;
8498
8499
8500
8501
8502 for (i = 0; i < it->cmp_it.nchars; i++)
8503 bidi_move_to_visually_next (&it->bidi_it);
8504 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8505 IT_CHARPOS (*it) = it->bidi_it.charpos;
8506 }
8507
8508 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8509 && it->cmp_it.to < it->cmp_it.nglyphs)
8510 {
8511
8512
8513 it->cmp_it.from = it->cmp_it.to;
8514 }
8515 else if ((it->bidi_p && it->cmp_it.reversed_p)
8516 && it->cmp_it.from > 0)
8517 {
8518
8519
8520 it->cmp_it.to = it->cmp_it.from;
8521 }
8522 else
8523 {
8524
8525
8526 ptrdiff_t stop = it->end_charpos;
8527
8528 if (it->bidi_it.scan_dir < 0)
8529
8530
8531 stop = -1;
8532 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8533 IT_BYTEPOS (*it), stop, Qnil);
8534 }
8535 }
8536 else
8537 {
8538 eassert (it->len != 0);
8539
8540 if (!it->bidi_p)
8541 {
8542 IT_BYTEPOS (*it) += it->len;
8543 IT_CHARPOS (*it) += 1;
8544 }
8545 else
8546 {
8547 int prev_scan_dir = it->bidi_it.scan_dir;
8548
8549
8550 if (it->bidi_it.new_paragraph)
8551 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
8552 false);
8553 bidi_move_to_visually_next (&it->bidi_it);
8554 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8555 IT_CHARPOS (*it) = it->bidi_it.charpos;
8556 if (prev_scan_dir != it->bidi_it.scan_dir)
8557 {
8558
8559
8560 ptrdiff_t stop = it->end_charpos;
8561 if (it->bidi_it.scan_dir < 0)
8562 stop = -1;
8563 composition_compute_stop_pos (&it->cmp_it, IT_CHARPOS (*it),
8564 IT_BYTEPOS (*it), stop, Qnil);
8565 }
8566 }
8567 eassert (IT_BYTEPOS (*it) == CHAR_TO_BYTE (IT_CHARPOS (*it)));
8568 }
8569 break;
8570
8571 case GET_FROM_C_STRING:
8572
8573 if (!it->bidi_p
8574
8575
8576
8577
8578 || IT_CHARPOS (*it) >= it->bidi_it.string.schars)
8579 {
8580 IT_BYTEPOS (*it) += it->len;
8581 IT_CHARPOS (*it) += 1;
8582 }
8583 else
8584 {
8585 bidi_move_to_visually_next (&it->bidi_it);
8586 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8587 IT_CHARPOS (*it) = it->bidi_it.charpos;
8588 }
8589 break;
8590
8591 case GET_FROM_DISPLAY_VECTOR:
8592
8593
8594
8595
8596 ++it->current.dpvec_index;
8597
8598
8599
8600 it->face_id = it->saved_face_id;
8601
8602 if (it->dpvec + it->current.dpvec_index >= it->dpend)
8603 {
8604 bool recheck_faces = it->ellipsis_p;
8605
8606 if (it->s)
8607 it->method = GET_FROM_C_STRING;
8608 else if (STRINGP (it->string))
8609 it->method = GET_FROM_STRING;
8610 else
8611 {
8612 it->method = GET_FROM_BUFFER;
8613 it->object = it->w->contents;
8614 }
8615
8616 it->dpvec = NULL;
8617 it->current.dpvec_index = -1;
8618
8619
8620 if (it->dpvec_char_len < 0)
8621 reseat_at_next_visible_line_start (it, true);
8622 else if (it->dpvec_char_len > 0)
8623 {
8624 it->len = it->dpvec_char_len;
8625 set_iterator_to_next (it, reseat_p);
8626 }
8627
8628
8629 if (recheck_faces)
8630 {
8631 if (it->method == GET_FROM_STRING)
8632 it->stop_charpos = IT_STRING_CHARPOS (*it);
8633 else
8634 it->stop_charpos = IT_CHARPOS (*it);
8635 }
8636 }
8637 break;
8638
8639 case GET_FROM_STRING:
8640
8641 eassert (it->s == NULL && STRINGP (it->string));
8642
8643
8644
8645
8646
8647 if (it->current.overlay_string_index >= 0)
8648 {
8649
8650
8651
8652 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8653 goto consider_string_end;
8654 }
8655 else
8656 {
8657
8658
8659 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
8660 goto consider_string_end;
8661 }
8662 if (it->cmp_it.id >= 0)
8663 {
8664
8665
8666
8667 if (! it->bidi_p)
8668 {
8669 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
8670 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
8671 }
8672 else
8673 {
8674 int i;
8675
8676 for (i = 0; i < it->cmp_it.nchars; i++)
8677 bidi_move_to_visually_next (&it->bidi_it);
8678 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8679 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8680 }
8681
8682
8683
8684 if ((! it->bidi_p || ! it->cmp_it.reversed_p)
8685 && (it->cmp_it.to < it->cmp_it.nglyphs))
8686 {
8687
8688
8689 it->cmp_it.from = it->cmp_it.to;
8690 }
8691 else if ((it->bidi_p && it->cmp_it.reversed_p)
8692 && it->cmp_it.from > 0)
8693 {
8694
8695
8696 it->cmp_it.to = it->cmp_it.from;
8697 }
8698 else
8699 {
8700
8701
8702
8703
8704
8705
8706 ptrdiff_t stop = SCHARS (it->string);
8707
8708 if (it->bidi_p && it->bidi_it.scan_dir < 0)
8709 stop = -1;
8710 else if (it->end_charpos < stop)
8711 {
8712
8713
8714
8715 stop = it->end_charpos;
8716 }
8717 composition_compute_stop_pos (&it->cmp_it,
8718 IT_STRING_CHARPOS (*it),
8719 IT_STRING_BYTEPOS (*it), stop,
8720 it->string);
8721 }
8722 }
8723 else
8724 {
8725 if (!it->bidi_p
8726
8727
8728
8729
8730
8731 || IT_STRING_CHARPOS (*it) >= it->bidi_it.string.schars)
8732 {
8733 IT_STRING_BYTEPOS (*it) += it->len;
8734 IT_STRING_CHARPOS (*it) += 1;
8735 }
8736 else
8737 {
8738 int prev_scan_dir = it->bidi_it.scan_dir;
8739
8740 bidi_move_to_visually_next (&it->bidi_it);
8741 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8742 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8743
8744
8745 if (prev_scan_dir != it->bidi_it.scan_dir)
8746 {
8747 ptrdiff_t stop = SCHARS (it->string);
8748
8749 if (it->bidi_it.scan_dir < 0)
8750 stop = -1;
8751 else if (it->end_charpos < stop)
8752 stop = it->end_charpos;
8753
8754 composition_compute_stop_pos (&it->cmp_it,
8755 IT_STRING_CHARPOS (*it),
8756 IT_STRING_BYTEPOS (*it), stop,
8757 it->string);
8758 }
8759 }
8760 }
8761
8762 consider_string_end:
8763
8764 if (it->current.overlay_string_index >= 0)
8765 {
8766
8767
8768 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
8769 {
8770 it->ellipsis_p = false;
8771 next_overlay_string (it);
8772 if (it->ellipsis_p)
8773 setup_for_ellipsis (it, 0);
8774 }
8775 }
8776 else
8777 {
8778
8779
8780
8781
8782 if (IT_STRING_CHARPOS (*it) == SCHARS (it->string)
8783 && it->sp > 0)
8784 {
8785 pop_it (it);
8786 if (it->method == GET_FROM_STRING)
8787 goto consider_string_end;
8788 }
8789 }
8790 break;
8791
8792 case GET_FROM_IMAGE:
8793 case GET_FROM_STRETCH:
8794 case GET_FROM_XWIDGET:
8795
8796
8797
8798
8799 eassert (it->sp > 0);
8800 pop_it (it);
8801 if (it->method == GET_FROM_STRING)
8802 goto consider_string_end;
8803 break;
8804
8805 default:
8806
8807 emacs_abort ();
8808 }
8809
8810 eassert (it->method != GET_FROM_STRING
8811 || (STRINGP (it->string)
8812 && IT_STRING_CHARPOS (*it) >= 0));
8813 }
8814
8815
8816
8817
8818
8819
8820
8821
8822
8823
8824 static bool
8825 next_element_from_display_vector (struct it *it)
8826 {
8827 Lisp_Object gc;
8828 int prev_face_id = it->face_id;
8829 int next_face_id;
8830
8831
8832 eassert (it->dpvec && it->current.dpvec_index >= 0);
8833
8834 it->face_id = it->saved_face_id;
8835
8836
8837
8838 if (it->dpend - it->dpvec > 0
8839 && (gc = it->dpvec[it->current.dpvec_index], GLYPH_CODE_P (gc)))
8840 {
8841 struct face *this_face, *prev_face, *next_face;
8842
8843 it->c = GLYPH_CODE_CHAR (gc);
8844 it->len = CHAR_BYTES (it->c);
8845
8846
8847
8848
8849 if (it->dpvec_face_id >= 0)
8850 it->face_id = it->dpvec_face_id;
8851 else
8852 {
8853 int lface_id = GLYPH_CODE_FACE (gc);
8854 if (lface_id > 0)
8855 it->face_id = merge_faces (it->w, Qt, lface_id,
8856 it->saved_face_id);
8857 }
8858
8859
8860
8861
8862 this_face = FACE_FROM_ID_OR_NULL (it->f, it->face_id);
8863 prev_face = FACE_FROM_ID_OR_NULL (it->f, prev_face_id);
8864
8865
8866 it->start_of_box_run_p = (this_face && this_face->box != FACE_NO_BOX
8867 && (!prev_face
8868 || prev_face->box == FACE_NO_BOX));
8869
8870
8871
8872
8873 next_face_id = it->saved_face_id;
8874 if (it->current.dpvec_index < it->dpend - it->dpvec - 1)
8875 {
8876 if (it->dpvec_face_id >= 0)
8877 next_face_id = it->dpvec_face_id;
8878 else
8879 {
8880 Lisp_Object gc = it->dpvec[it->current.dpvec_index + 1];
8881 int lface_id = GLYPH_CODE_P (gc) ? GLYPH_CODE_FACE (gc) : 0;
8882
8883 if (lface_id > 0)
8884 next_face_id = merge_faces (it->w, Qt, lface_id,
8885 it->saved_face_id);
8886 }
8887 }
8888 next_face = FACE_FROM_ID_OR_NULL (it->f, next_face_id);
8889 if (this_face && this_face->box != FACE_NO_BOX
8890 && (!next_face || next_face->box == FACE_NO_BOX))
8891 it->end_of_box_run_p = true;
8892 it->face_box_p = this_face && this_face->box != FACE_NO_BOX;
8893 }
8894 else
8895
8896 it->c = ' ', it->len = 1;
8897
8898
8899
8900
8901 it->what = IT_CHARACTER;
8902 return true;
8903 }
8904
8905
8906
8907 static void
8908 get_visually_first_element (struct it *it)
8909 {
8910 bool string_p = STRINGP (it->string) || it->s;
8911 ptrdiff_t eob = (string_p ? it->bidi_it.string.schars : ZV);
8912 ptrdiff_t bob;
8913 ptrdiff_t obegv = BEGV;
8914
8915 SET_WITH_NARROWED_BEGV (it, bob,
8916 string_p ? 0 :
8917 IT_CHARPOS (*it) < BEGV ? obegv : BEGV,
8918 it->medium_narrowing_begv);
8919
8920 if (STRINGP (it->string))
8921 {
8922 it->bidi_it.charpos = IT_STRING_CHARPOS (*it);
8923 it->bidi_it.bytepos = IT_STRING_BYTEPOS (*it);
8924 }
8925 else
8926 {
8927 it->bidi_it.charpos = IT_CHARPOS (*it);
8928 it->bidi_it.bytepos = IT_BYTEPOS (*it);
8929 }
8930
8931 if (it->bidi_it.charpos == eob)
8932 {
8933
8934
8935
8936 it->bidi_it.first_elt = false;
8937 }
8938 else if (it->bidi_it.charpos == bob
8939 || (!string_p
8940 && (FETCH_BYTE (it->bidi_it.bytepos - 1) == '\n'
8941 || FETCH_BYTE (it->bidi_it.bytepos) == '\n')))
8942 {
8943
8944
8945 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8946 bidi_move_to_visually_next (&it->bidi_it);
8947 }
8948 else
8949 {
8950 ptrdiff_t orig_bytepos = it->bidi_it.bytepos;
8951
8952
8953
8954
8955 if (string_p)
8956 it->bidi_it.charpos = it->bidi_it.bytepos = 0;
8957 else
8958 SET_WITH_NARROWED_BEGV (it, it->bidi_it.charpos,
8959 find_newline_no_quit (IT_CHARPOS (*it),
8960 IT_BYTEPOS (*it), -1,
8961 &it->bidi_it.bytepos),
8962 it->medium_narrowing_begv);
8963 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it, true);
8964 do
8965 {
8966
8967
8968 bidi_move_to_visually_next (&it->bidi_it);
8969 }
8970 while (it->bidi_it.bytepos != orig_bytepos
8971 && it->bidi_it.charpos < eob);
8972 }
8973
8974
8975 if (STRINGP (it->string))
8976 {
8977 IT_STRING_CHARPOS (*it) = it->bidi_it.charpos;
8978 IT_STRING_BYTEPOS (*it) = it->bidi_it.bytepos;
8979 }
8980 else
8981 {
8982 IT_CHARPOS (*it) = it->bidi_it.charpos;
8983 IT_BYTEPOS (*it) = it->bidi_it.bytepos;
8984 }
8985
8986 if (STRINGP (it->string) || !it->s)
8987 {
8988 ptrdiff_t stop, charpos, bytepos;
8989
8990 if (STRINGP (it->string))
8991 {
8992 eassert (!it->s);
8993 stop = SCHARS (it->string);
8994 if (stop > it->end_charpos)
8995 stop = it->end_charpos;
8996 charpos = IT_STRING_CHARPOS (*it);
8997 bytepos = IT_STRING_BYTEPOS (*it);
8998 }
8999 else
9000 {
9001 stop = it->end_charpos;
9002 charpos = IT_CHARPOS (*it);
9003 bytepos = IT_BYTEPOS (*it);
9004 }
9005 if (it->bidi_it.scan_dir < 0)
9006 stop = -1;
9007 composition_compute_stop_pos (&it->cmp_it, charpos, bytepos, stop,
9008 it->string);
9009 }
9010 }
9011
9012
9013
9014
9015
9016
9017 static bool
9018 next_element_from_string (struct it *it)
9019 {
9020 struct text_pos position;
9021
9022 eassert (STRINGP (it->string));
9023 eassert (!it->bidi_p || EQ (it->string, it->bidi_it.string.lstring));
9024 eassert (IT_STRING_CHARPOS (*it) >= 0);
9025 position = it->current.string_pos;
9026
9027
9028
9029
9030
9031 if (it->bidi_p && it->bidi_it.first_elt)
9032 {
9033 get_visually_first_element (it);
9034 SET_TEXT_POS (position, IT_STRING_CHARPOS (*it), IT_STRING_BYTEPOS (*it));
9035 }
9036
9037
9038 if (IT_STRING_CHARPOS (*it) < it->end_charpos)
9039 {
9040 if (IT_STRING_CHARPOS (*it) >= it->stop_charpos)
9041 {
9042 if (!(!it->bidi_p
9043 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9044 || IT_STRING_CHARPOS (*it) == it->stop_charpos))
9045 {
9046
9047
9048
9049
9050
9051
9052 handle_stop_backwards (it, it->stop_charpos);
9053 return GET_NEXT_DISPLAY_ELEMENT (it);
9054 }
9055 else
9056 {
9057 if (it->bidi_p)
9058 {
9059
9060
9061 it->prev_stop = it->stop_charpos;
9062
9063
9064
9065 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9066 it->base_level_stop = it->stop_charpos;
9067 }
9068 handle_stop (it);
9069
9070
9071
9072 return GET_NEXT_DISPLAY_ELEMENT (it);
9073 }
9074 }
9075 else if (it->bidi_p
9076
9077
9078
9079 && IT_STRING_CHARPOS (*it) < it->prev_stop
9080
9081
9082
9083
9084 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9085 {
9086
9087
9088
9089
9090 if (it->base_level_stop <= 0
9091 || IT_STRING_CHARPOS (*it) < it->base_level_stop)
9092 it->base_level_stop = 0;
9093 handle_stop_backwards (it, it->base_level_stop);
9094 return GET_NEXT_DISPLAY_ELEMENT (it);
9095 }
9096 }
9097
9098 if (it->current.overlay_string_index >= 0)
9099 {
9100
9101
9102
9103 if (IT_STRING_CHARPOS (*it) >= SCHARS (it->string))
9104 {
9105 it->what = IT_EOB;
9106 return false;
9107 }
9108 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9109 IT_STRING_BYTEPOS (*it),
9110 it->bidi_it.scan_dir < 0
9111 ? -1
9112 : SCHARS (it->string))
9113 && next_element_from_composition (it))
9114 {
9115 return true;
9116 }
9117 else if (STRING_MULTIBYTE (it->string))
9118 {
9119 const unsigned char *s = (SDATA (it->string)
9120 + IT_STRING_BYTEPOS (*it));
9121 it->c = check_char_and_length (s, &it->len);
9122 }
9123 else
9124 {
9125 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9126 it->len = 1;
9127 }
9128 }
9129 else
9130 {
9131
9132
9133
9134
9135 if (IT_STRING_CHARPOS (*it) >= it->end_charpos)
9136 {
9137 it->what = IT_EOB;
9138 return false;
9139 }
9140 else if (IT_STRING_CHARPOS (*it) >= it->string_nchars)
9141 {
9142
9143 it->c = ' ', it->len = 1;
9144 CHARPOS (position) = BYTEPOS (position) = -1;
9145 }
9146 else if (CHAR_COMPOSED_P (it, IT_STRING_CHARPOS (*it),
9147 IT_STRING_BYTEPOS (*it),
9148 it->bidi_it.scan_dir < 0
9149 ? -1
9150 : it->string_nchars)
9151 && next_element_from_composition (it))
9152 {
9153 return true;
9154 }
9155 else if (STRING_MULTIBYTE (it->string))
9156 {
9157 const unsigned char *s = (SDATA (it->string)
9158 + IT_STRING_BYTEPOS (*it));
9159 it->c = check_char_and_length (s, &it->len);
9160 }
9161 else
9162 {
9163 it->c = SREF (it->string, IT_STRING_BYTEPOS (*it));
9164 it->len = 1;
9165 }
9166 }
9167
9168
9169 it->what = IT_CHARACTER;
9170 it->object = it->string;
9171 it->position = position;
9172 return true;
9173 }
9174
9175
9176
9177
9178
9179
9180
9181
9182
9183 static bool
9184 next_element_from_c_string (struct it *it)
9185 {
9186 bool success_p = true;
9187
9188 eassert (it->s);
9189 eassert (!it->bidi_p || it->s == it->bidi_it.string.s);
9190 it->what = IT_CHARACTER;
9191 BYTEPOS (it->position) = CHARPOS (it->position) = 0;
9192 it->object = make_fixnum (0);
9193
9194
9195
9196
9197
9198 if (it->bidi_p && it->bidi_it.first_elt)
9199 get_visually_first_element (it);
9200
9201
9202
9203
9204 if (IT_CHARPOS (*it) >= it->end_charpos)
9205 {
9206
9207 it->what = IT_EOB;
9208 success_p = false;
9209 }
9210 else if (IT_CHARPOS (*it) >= it->string_nchars)
9211 {
9212
9213 it->c = ' ', it->len = 1;
9214 BYTEPOS (it->position) = CHARPOS (it->position) = -1;
9215 }
9216 else if (it->multibyte_p)
9217 it->c = check_char_and_length (it->s + IT_BYTEPOS (*it), &it->len);
9218 else
9219 it->c = it->s[IT_BYTEPOS (*it)], it->len = 1;
9220
9221 return success_p;
9222 }
9223
9224
9225
9226
9227
9228
9229
9230 static bool
9231 next_element_from_ellipsis (struct it *it)
9232 {
9233 if (it->selective_display_ellipsis_p)
9234 setup_for_ellipsis (it, it->len);
9235 else
9236 {
9237
9238
9239
9240
9241 it->saved_face_id = it->face_id;
9242 it->method = GET_FROM_BUFFER;
9243 it->object = it->w->contents;
9244 reseat_at_next_visible_line_start (it, true);
9245 it->face_before_selective_p = true;
9246 }
9247
9248 return GET_NEXT_DISPLAY_ELEMENT (it);
9249 }
9250
9251
9252
9253
9254
9255
9256
9257 static bool
9258 next_element_from_image (struct it *it)
9259 {
9260 it->what = IT_IMAGE;
9261 return true;
9262 }
9263
9264 static bool
9265 next_element_from_xwidget (struct it *it)
9266 {
9267 it->what = IT_XWIDGET;
9268 return true;
9269 }
9270
9271
9272
9273
9274
9275
9276 static bool
9277 next_element_from_stretch (struct it *it)
9278 {
9279 it->what = IT_STRETCH;
9280 return true;
9281 }
9282
9283
9284
9285
9286
9287
9288 static void
9289 compute_stop_pos_backwards (struct it *it)
9290 {
9291 const int SCAN_BACK_LIMIT = 1000;
9292 struct text_pos pos;
9293 struct display_pos save_current = it->current;
9294 struct text_pos save_position = it->position;
9295 ptrdiff_t charpos = IT_CHARPOS (*it);
9296 ptrdiff_t where_we_are = charpos;
9297 ptrdiff_t save_stop_pos = it->stop_charpos;
9298 ptrdiff_t save_end_pos = it->end_charpos;
9299
9300 eassert (NILP (it->string) && !it->s);
9301 eassert (it->bidi_p);
9302 it->bidi_p = false;
9303 do
9304 {
9305 it->end_charpos = min (charpos + 1, ZV);
9306 charpos = max (charpos - SCAN_BACK_LIMIT, BEGV);
9307 SET_TEXT_POS (pos, charpos, CHAR_TO_BYTE (charpos));
9308 reseat_1 (it, pos, false);
9309 compute_stop_pos (it);
9310
9311 if (it->stop_charpos <= charpos)
9312 emacs_abort ();
9313 }
9314 while (charpos > BEGV && it->stop_charpos >= it->end_charpos);
9315
9316 if (it->stop_charpos <= where_we_are)
9317 it->prev_stop = it->stop_charpos;
9318 else
9319 it->prev_stop = BEGV;
9320 it->bidi_p = true;
9321 it->current = save_current;
9322 it->position = save_position;
9323 it->stop_charpos = save_stop_pos;
9324 it->end_charpos = save_end_pos;
9325 }
9326
9327
9328
9329
9330
9331
9332
9333
9334
9335 static void
9336 handle_stop_backwards (struct it *it, ptrdiff_t charpos)
9337 {
9338 bool bufp = !STRINGP (it->string);
9339 ptrdiff_t where_we_are = (bufp ? IT_CHARPOS (*it) : IT_STRING_CHARPOS (*it));
9340 struct display_pos save_current = it->current;
9341 struct text_pos save_position = it->position;
9342 struct composition_it save_cmp_it = it->cmp_it;
9343 struct text_pos pos1;
9344 ptrdiff_t next_stop;
9345
9346
9347 eassert (it->bidi_p);
9348 it->bidi_p = false;
9349 do
9350 {
9351 it->prev_stop = charpos;
9352 if (bufp)
9353 {
9354 SET_TEXT_POS (pos1, charpos, CHAR_TO_BYTE (charpos));
9355 reseat_1 (it, pos1, false);
9356 }
9357 else
9358 it->current.string_pos = string_pos (charpos, it->string);
9359 compute_stop_pos (it);
9360
9361 if (it->stop_charpos <= it->prev_stop)
9362 emacs_abort ();
9363 charpos = it->stop_charpos;
9364 }
9365 while (charpos <= where_we_are);
9366
9367 it->bidi_p = true;
9368 it->current = save_current;
9369 it->position = save_position;
9370 it->cmp_it = save_cmp_it;
9371 next_stop = it->stop_charpos;
9372 it->stop_charpos = it->prev_stop;
9373 handle_stop (it);
9374 it->stop_charpos = next_stop;
9375 }
9376
9377
9378
9379
9380
9381
9382 static bool
9383 next_element_from_buffer (struct it *it)
9384 {
9385 bool success_p = true;
9386
9387 eassert (IT_CHARPOS (*it) >= BEGV);
9388 eassert (NILP (it->string) && !it->s);
9389 eassert (!it->bidi_p
9390 || (NILP (it->bidi_it.string.lstring)
9391 && it->bidi_it.string.s == NULL));
9392
9393
9394
9395
9396
9397 if (it->bidi_p && it->bidi_it.first_elt)
9398 {
9399 get_visually_first_element (it);
9400 SET_TEXT_POS (it->position, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9401 }
9402
9403 if (IT_CHARPOS (*it) >= it->stop_charpos)
9404 {
9405 if (IT_CHARPOS (*it) >= it->end_charpos)
9406 {
9407 bool overlay_strings_follow_p;
9408
9409
9410
9411 if (it->overlay_strings_at_end_processed_p)
9412 overlay_strings_follow_p = false;
9413 else
9414 {
9415 it->overlay_strings_at_end_processed_p = true;
9416 overlay_strings_follow_p = get_overlay_strings (it, 0);
9417 }
9418
9419 if (overlay_strings_follow_p)
9420 success_p = GET_NEXT_DISPLAY_ELEMENT (it);
9421 else
9422 {
9423 it->what = IT_EOB;
9424 it->position = it->current.pos;
9425 success_p = false;
9426 }
9427 }
9428 else if (!(!it->bidi_p
9429 || BIDI_AT_BASE_LEVEL (it->bidi_it)
9430 || IT_CHARPOS (*it) == it->stop_charpos))
9431 {
9432
9433
9434
9435
9436
9437
9438 handle_stop_backwards (it, it->stop_charpos);
9439 it->ignore_overlay_strings_at_pos_p = false;
9440 return GET_NEXT_DISPLAY_ELEMENT (it);
9441 }
9442 else
9443 {
9444 if (it->bidi_p)
9445 {
9446
9447
9448 it->prev_stop = it->stop_charpos;
9449
9450
9451
9452 if (BIDI_AT_BASE_LEVEL (it->bidi_it))
9453 it->base_level_stop = it->stop_charpos;
9454 }
9455 handle_stop (it);
9456 it->ignore_overlay_strings_at_pos_p = false;
9457 return GET_NEXT_DISPLAY_ELEMENT (it);
9458 }
9459 }
9460 else if (it->bidi_p
9461
9462
9463
9464 && IT_CHARPOS (*it) < it->prev_stop
9465
9466
9467
9468
9469 && !BIDI_AT_BASE_LEVEL (it->bidi_it))
9470 {
9471 if (it->base_level_stop <= 0
9472 || IT_CHARPOS (*it) < it->base_level_stop)
9473 {
9474
9475
9476
9477
9478 it->base_level_stop = BEGV;
9479 compute_stop_pos_backwards (it);
9480 handle_stop_backwards (it, it->prev_stop);
9481 }
9482 else
9483 handle_stop_backwards (it, it->base_level_stop);
9484 it->ignore_overlay_strings_at_pos_p = false;
9485 return GET_NEXT_DISPLAY_ELEMENT (it);
9486 }
9487 else
9488 {
9489
9490
9491 unsigned char *p;
9492 ptrdiff_t stop;
9493
9494
9495
9496 it->ignore_overlay_strings_at_pos_p = false;
9497
9498 if (composition_break_at_point
9499 && !NILP (BVAR (current_buffer, enable_multibyte_characters))
9500 && !NILP (Vauto_composition_mode))
9501 {
9502
9503 if (it->bidi_it.scan_dir < 0)
9504 stop = (PT <= IT_CHARPOS (*it)) ? PT : -1;
9505 else
9506 stop = (IT_CHARPOS (*it) < PT
9507 && PT < it->end_charpos) ? PT : it->end_charpos;
9508 }
9509 else
9510 stop = it->bidi_it.scan_dir < 0 ? -1 : it->end_charpos;
9511 if (CHAR_COMPOSED_P (it, IT_CHARPOS (*it), IT_BYTEPOS (*it),
9512 stop)
9513 && next_element_from_composition (it))
9514 {
9515 return true;
9516 }
9517
9518
9519 p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
9520 if (it->multibyte_p && !ASCII_CHAR_P (*p))
9521 it->c = string_char_and_length (p, &it->len);
9522 else
9523 it->c = *p, it->len = 1;
9524
9525
9526 it->what = IT_CHARACTER;
9527 it->object = it->w->contents;
9528 it->position = it->current.pos;
9529
9530
9531
9532 if (it->selective)
9533 {
9534 if (it->c == '\n')
9535 {
9536
9537
9538 if (it->selective > 0
9539 && IT_CHARPOS (*it) + 1 < ZV
9540 && indented_beyond_p (IT_CHARPOS (*it) + 1,
9541 IT_BYTEPOS (*it) + 1,
9542 it->selective))
9543 {
9544 success_p = next_element_from_ellipsis (it);
9545 it->dpvec_char_len = -1;
9546 }
9547 }
9548 else if (it->c == '\r' && it->selective == -1)
9549 {
9550
9551
9552
9553 success_p = next_element_from_ellipsis (it);
9554 it->dpvec_char_len = -1;
9555 }
9556 }
9557 }
9558
9559
9560 eassert (!success_p || it->what != IT_CHARACTER || it->len > 0);
9561 return success_p;
9562 }
9563
9564
9565
9566
9567
9568
9569
9570 static bool
9571 next_element_from_composition (struct it *it)
9572 {
9573 it->what = IT_COMPOSITION;
9574 it->len = it->cmp_it.nbytes;
9575 if (STRINGP (it->string))
9576 {
9577 if (it->c < 0)
9578 {
9579 IT_STRING_CHARPOS (*it) += it->cmp_it.nchars;
9580 IT_STRING_BYTEPOS (*it) += it->cmp_it.nbytes;
9581 return false;
9582 }
9583 it->position = it->current.string_pos;
9584 it->object = it->string;
9585 it->c = composition_update_it (&it->cmp_it, IT_STRING_CHARPOS (*it),
9586 IT_STRING_BYTEPOS (*it), it->string);
9587 }
9588 else
9589 {
9590 if (it->c < 0)
9591 {
9592 IT_CHARPOS (*it) += it->cmp_it.nchars;
9593 IT_BYTEPOS (*it) += it->cmp_it.nbytes;
9594 if (it->bidi_p)
9595 {
9596 if (it->bidi_it.new_paragraph)
9597 bidi_paragraph_init (it->paragraph_embedding, &it->bidi_it,
9598 false);
9599
9600
9601 while (it->bidi_it.charpos < IT_CHARPOS (*it))
9602 bidi_move_to_visually_next (&it->bidi_it);
9603 }
9604 return false;
9605 }
9606 it->position = it->current.pos;
9607 it->object = it->w->contents;
9608 it->c = composition_update_it (&it->cmp_it, IT_CHARPOS (*it),
9609 IT_BYTEPOS (*it), Qnil);
9610 }
9611 return true;
9612 }
9613
9614
9615
9616
9617
9618
9619
9620
9621
9622
9623 #define IT_POS_VALID_AFTER_MOVE_P(it) \
9624 ((it)->method != GET_FROM_STRING || IT_STRING_CHARPOS (*it) == 0)
9625
9626
9627
9628
9629
9630
9631
9632
9633
9634
9635
9636
9637
9638
9639
9640
9641
9642
9643
9644
9645
9646
9647
9648
9649
9650
9651
9652
9653
9654
9655
9656
9657
9658
9659
9660 static enum move_it_result
9661 move_it_in_display_line_to (struct it *it,
9662 ptrdiff_t to_charpos, int to_x,
9663 enum move_operation_enum op)
9664 {
9665 enum move_it_result result = MOVE_UNDEFINED;
9666 struct glyph_row *saved_glyph_row;
9667 struct it wrap_it, atpos_it, atx_it, ppos_it;
9668 void *wrap_data = NULL, *atpos_data = NULL, *atx_data = NULL;
9669 void *ppos_data = NULL;
9670 bool may_wrap = false;
9671 enum it_method prev_method = it->method;
9672 ptrdiff_t closest_pos UNINIT;
9673 ptrdiff_t prev_pos = IT_CHARPOS (*it);
9674 bool saw_smaller_pos = prev_pos < to_charpos;
9675 bool line_number_pending = false;
9676
9677
9678 saved_glyph_row = it->glyph_row;
9679 it->glyph_row = NULL;
9680
9681
9682
9683
9684
9685
9686 wrap_it.sp = -1;
9687 atpos_it.sp = -1;
9688 atx_it.sp = -1;
9689
9690
9691
9692
9693
9694
9695
9696
9697 if (it->bidi_p)
9698 {
9699 if ((op & MOVE_TO_POS) && IT_CHARPOS (*it) >= to_charpos)
9700 {
9701 SAVE_IT (ppos_it, *it, ppos_data);
9702 closest_pos = IT_CHARPOS (*it);
9703 }
9704 else
9705 closest_pos = ZV;
9706 }
9707
9708 #define BUFFER_POS_REACHED_P() \
9709 ((op & MOVE_TO_POS) != 0 \
9710 && BUFFERP (it->object) \
9711 && (IT_CHARPOS (*it) == to_charpos \
9712 || ((!it->bidi_p \
9713 || BIDI_AT_BASE_LEVEL (it->bidi_it)) \
9714 && IT_CHARPOS (*it) > to_charpos) \
9715 || (it->what == IT_COMPOSITION \
9716 && ((IT_CHARPOS (*it) > to_charpos \
9717 && to_charpos >= it->cmp_it.charpos) \
9718 || (IT_CHARPOS (*it) < to_charpos \
9719 && to_charpos <= it->cmp_it.charpos)))) \
9720 && (it->method == GET_FROM_BUFFER \
9721 || (it->method == GET_FROM_DISPLAY_VECTOR \
9722 && it->dpvec + it->current.dpvec_index + 1 >= it->dpend)))
9723
9724 if (it->hpos == 0)
9725 {
9726
9727
9728
9729
9730 if (!((op && MOVE_TO_X) && to_x == it->first_visible_x)
9731 && should_produce_line_number (it))
9732 {
9733 if (it->current_x == it->first_visible_x)
9734 maybe_produce_line_number (it);
9735 else
9736 line_number_pending = true;
9737 }
9738
9739 if (it->area == TEXT_AREA && !it->string_from_prefix_prop_p)
9740 handle_line_prefix (it);
9741 }
9742
9743 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9744 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
9745
9746 while (true)
9747 {
9748 int x, i, ascent = 0, descent = 0;
9749
9750
9751 #define IT_RESET_X_ASCENT_DESCENT(IT) \
9752 ((IT)->current_x = x, (IT)->max_ascent = ascent, \
9753 (IT)->max_descent = descent)
9754
9755
9756
9757 if ((op & MOVE_TO_POS) != 0
9758 && BUFFERP (it->object)
9759 && it->method == GET_FROM_BUFFER
9760 && (((!it->bidi_p
9761
9762
9763
9764
9765 || BIDI_AT_BASE_LEVEL (it->bidi_it))
9766 && IT_CHARPOS (*it) > to_charpos)
9767 || (it->bidi_p
9768 && (prev_method == GET_FROM_IMAGE
9769 || prev_method == GET_FROM_STRETCH
9770 || prev_method == GET_FROM_STRING)
9771
9772 && ((prev_pos < to_charpos
9773 && IT_CHARPOS (*it) >= to_charpos)
9774
9775 || (prev_pos > to_charpos
9776 && IT_CHARPOS (*it) <= to_charpos)))))
9777 {
9778 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9779 {
9780 result = MOVE_POS_MATCH_OR_ZV;
9781 break;
9782 }
9783 else if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
9784
9785
9786
9787 SAVE_IT (atpos_it, *it, atpos_data);
9788 }
9789
9790
9791
9792
9793
9794 if (!get_next_display_element (it))
9795 {
9796 result = MOVE_POS_MATCH_OR_ZV;
9797 break;
9798 }
9799
9800 if (it->line_wrap == TRUNCATE)
9801 {
9802
9803
9804
9805
9806
9807
9808 if (BUFFER_POS_REACHED_P ()
9809 && (it->pixel_width > 0
9810 || IT_CHARPOS (*it) > to_charpos
9811 || it->area != TEXT_AREA))
9812 {
9813 result = MOVE_POS_MATCH_OR_ZV;
9814 break;
9815 }
9816 }
9817 else
9818 {
9819 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
9820 {
9821 bool next_may_wrap = may_wrap;
9822
9823 if (char_can_wrap_after (it))
9824 next_may_wrap = true;
9825 else
9826 next_may_wrap = false;
9827
9828 if (may_wrap && char_can_wrap_before (it))
9829 {
9830
9831
9832
9833
9834
9835 if (atpos_it.sp >= 0)
9836 {
9837 RESTORE_IT (it, &atpos_it, atpos_data);
9838 result = MOVE_POS_MATCH_OR_ZV;
9839 goto done;
9840 }
9841 if (atx_it.sp >= 0)
9842 {
9843 RESTORE_IT (it, &atx_it, atx_data);
9844 result = MOVE_X_REACHED;
9845 goto done;
9846 }
9847
9848 SAVE_IT (wrap_it, *it, wrap_data);
9849 }
9850
9851 may_wrap = next_may_wrap;
9852 }
9853 }
9854
9855
9856
9857 ascent = it->max_ascent;
9858 descent = it->max_descent;
9859
9860
9861
9862
9863
9864 x = it->current_x;
9865
9866 PRODUCE_GLYPHS (it);
9867
9868 if (it->area != TEXT_AREA)
9869 {
9870 prev_method = it->method;
9871 if (it->method == GET_FROM_BUFFER)
9872 prev_pos = IT_CHARPOS (*it);
9873 set_iterator_to_next (it, true);
9874 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
9875 SET_TEXT_POS (this_line_min_pos,
9876 IT_CHARPOS (*it), IT_BYTEPOS (*it));
9877 if (it->bidi_p
9878 && (op & MOVE_TO_POS)
9879 && IT_CHARPOS (*it) > to_charpos
9880 && IT_CHARPOS (*it) < closest_pos)
9881 closest_pos = IT_CHARPOS (*it);
9882 continue;
9883 }
9884
9885
9886
9887
9888
9889
9890
9891
9892
9893
9894
9895
9896
9897
9898
9899
9900
9901
9902
9903 if (it->nglyphs)
9904 {
9905
9906
9907 int single_glyph_width = it->pixel_width / it->nglyphs;
9908 int new_x;
9909 int x_before_this_char = x;
9910 int hpos_before_this_char = it->hpos;
9911
9912 for (i = 0; i < it->nglyphs; ++i, x = new_x)
9913 {
9914 new_x = x + single_glyph_width;
9915
9916
9917 if ((op & MOVE_TO_X) && new_x > to_x)
9918 {
9919 if (BUFFER_POS_REACHED_P ())
9920 {
9921 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9922 goto buffer_pos_reached;
9923 if (atpos_it.sp < 0)
9924 {
9925 SAVE_IT (atpos_it, *it, atpos_data);
9926 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
9927 }
9928 }
9929 else
9930 {
9931 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
9932 {
9933 it->current_x = x;
9934 result = MOVE_X_REACHED;
9935 break;
9936 }
9937 if (atx_it.sp < 0)
9938 {
9939 SAVE_IT (atx_it, *it, atx_data);
9940 IT_RESET_X_ASCENT_DESCENT (&atx_it);
9941 }
9942 }
9943 }
9944
9945 if (
9946 it->line_wrap != TRUNCATE
9947 && (
9948 new_x > it->last_visible_x
9949
9950
9951 || (new_x == it->last_visible_x
9952 && FRAME_WINDOW_P (it->f)
9953 && ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
9954 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
9955 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
9956 {
9957 bool moved_forward = false;
9958
9959 if (
9960
9961 it->hpos == 0
9962 || (new_x == it->last_visible_x
9963 && FRAME_WINDOW_P (it->f)))
9964 {
9965 ++it->hpos;
9966 it->current_x = new_x;
9967
9968
9969
9970 if (i == it->nglyphs - 1)
9971 {
9972
9973
9974
9975 if (BUFFER_POS_REACHED_P ())
9976 {
9977 bool can_wrap = true;
9978
9979
9980
9981
9982
9983 if (it->line_wrap == WORD_WRAP
9984 && wrap_it.sp >= 0
9985 && may_wrap
9986 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
9987 {
9988 struct it tem_it;
9989 void *tem_data = NULL;
9990
9991 SAVE_IT (tem_it, *it, tem_data);
9992 set_iterator_to_next (it, true);
9993 if (get_next_display_element (it)
9994 && !char_can_wrap_before (it))
9995 can_wrap = false;
9996 RESTORE_IT (it, &tem_it, tem_data);
9997 }
9998 if (it->line_wrap != WORD_WRAP
9999 || wrap_it.sp < 0
10000
10001
10002
10003
10004
10005
10006
10007 || (may_wrap && can_wrap
10008 && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10009 {
10010 it->hpos = hpos_before_this_char;
10011 it->current_x = x_before_this_char;
10012 result = MOVE_POS_MATCH_OR_ZV;
10013 break;
10014 }
10015 if (it->line_wrap == WORD_WRAP
10016 && atpos_it.sp < 0)
10017 {
10018 SAVE_IT (atpos_it, *it, atpos_data);
10019 atpos_it.current_x = x_before_this_char;
10020 atpos_it.hpos = hpos_before_this_char;
10021 }
10022 }
10023
10024 prev_method = it->method;
10025 if (it->method == GET_FROM_BUFFER)
10026 prev_pos = IT_CHARPOS (*it);
10027 set_iterator_to_next (it, true);
10028 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10029 SET_TEXT_POS (this_line_min_pos,
10030 IT_CHARPOS (*it), IT_BYTEPOS (*it));
10031
10032
10033
10034
10035
10036
10037
10038 if (!FRAME_WINDOW_P (it->f)
10039 || ((it->bidi_p
10040 && it->bidi_it.paragraph_dir == R2L)
10041 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10042 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10043 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10044 {
10045 if (!get_next_display_element (it))
10046 {
10047 result = MOVE_POS_MATCH_OR_ZV;
10048 break;
10049 }
10050 moved_forward = true;
10051 if (BUFFER_POS_REACHED_P ())
10052 {
10053 if (ITERATOR_AT_END_OF_LINE_P (it))
10054 result = MOVE_POS_MATCH_OR_ZV;
10055 else
10056 result = MOVE_LINE_CONTINUED;
10057 break;
10058 }
10059 if (ITERATOR_AT_END_OF_LINE_P (it)
10060 && (it->line_wrap != WORD_WRAP
10061 || wrap_it.sp < 0
10062 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)))
10063 {
10064 result = MOVE_NEWLINE_OR_CR;
10065 break;
10066 }
10067 }
10068 }
10069 }
10070 else
10071 IT_RESET_X_ASCENT_DESCENT (it);
10072
10073
10074
10075
10076
10077
10078 if (may_wrap && IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
10079
10080
10081
10082
10083
10084 && (!moved_forward || char_can_wrap_before (it)))
10085 {
10086
10087
10088 if ((op & MOVE_TO_X) && new_x == it->last_visible_x
10089 && atx_it.sp >= 0)
10090 {
10091 RESTORE_IT (it, &atx_it, atx_data);
10092 atpos_it.sp = -1;
10093 atx_it.sp = -1;
10094 result = MOVE_X_REACHED;
10095 break;
10096 }
10097 }
10098 else if (wrap_it.sp >= 0)
10099 {
10100 RESTORE_IT (it, &wrap_it, wrap_data);
10101 atpos_it.sp = -1;
10102 atx_it.sp = -1;
10103 }
10104
10105 move_trace ("move_it_in: continued at %td\n",
10106 IT_CHARPOS (*it));
10107 result = MOVE_LINE_CONTINUED;
10108 break;
10109 }
10110
10111 if (BUFFER_POS_REACHED_P ())
10112 {
10113 if (it->line_wrap != WORD_WRAP || wrap_it.sp < 0)
10114 goto buffer_pos_reached;
10115 if (it->line_wrap == WORD_WRAP && atpos_it.sp < 0)
10116 {
10117 SAVE_IT (atpos_it, *it, atpos_data);
10118 IT_RESET_X_ASCENT_DESCENT (&atpos_it);
10119 }
10120 }
10121
10122 if (new_x > it->first_visible_x)
10123 {
10124
10125
10126 if (line_number_pending)
10127 {
10128 line_number_pending = false;
10129 it->current_x = it->first_visible_x;
10130 maybe_produce_line_number (it);
10131 it->current_x += new_x - it->first_visible_x;
10132 }
10133
10134
10135 ++it->hpos;
10136 }
10137 }
10138
10139 if (result != MOVE_UNDEFINED)
10140 break;
10141 }
10142 else if (BUFFER_POS_REACHED_P ())
10143 {
10144 buffer_pos_reached:
10145 IT_RESET_X_ASCENT_DESCENT (it);
10146 result = MOVE_POS_MATCH_OR_ZV;
10147 break;
10148 }
10149 else if ((op & MOVE_TO_X) && it->current_x >= to_x)
10150 {
10151
10152
10153
10154
10155 eassert (it->nglyphs == 0);
10156 result = MOVE_X_REACHED;
10157 break;
10158 }
10159
10160
10161 if (ITERATOR_AT_END_OF_LINE_P (it))
10162 {
10163
10164
10165
10166
10167 if (it->bidi_p && (op & MOVE_TO_POS) != 0)
10168 {
10169 if (!saw_smaller_pos && IT_CHARPOS (*it) > to_charpos)
10170 {
10171 if (closest_pos < ZV)
10172 {
10173 RESTORE_IT (it, &ppos_it, ppos_data);
10174
10175
10176 if (closest_pos != to_charpos)
10177 move_it_in_display_line_to (it, closest_pos, -1,
10178 MOVE_TO_POS);
10179 result = MOVE_POS_MATCH_OR_ZV;
10180 }
10181 else
10182 goto buffer_pos_reached;
10183 }
10184 else if (it->line_wrap == WORD_WRAP && atpos_it.sp >= 0
10185 && IT_CHARPOS (*it) > to_charpos)
10186 goto buffer_pos_reached;
10187 else
10188 result = MOVE_NEWLINE_OR_CR;
10189 }
10190 else
10191 result = MOVE_NEWLINE_OR_CR;
10192
10193
10194
10195
10196 if (it->line_wrap == TRUNCATE
10197 && it->current_x <= it->first_visible_x
10198 && result == MOVE_NEWLINE_OR_CR
10199 && it->char_to_display == '\n')
10200 {
10201 it->max_ascent = it->ascent;
10202 it->max_descent = it->descent;
10203 }
10204
10205
10206
10207 if (result == MOVE_NEWLINE_OR_CR)
10208 it->constrain_row_ascent_descent_p = false;
10209 break;
10210 }
10211
10212 prev_method = it->method;
10213 if (it->method == GET_FROM_BUFFER)
10214 prev_pos = IT_CHARPOS (*it);
10215
10216
10217
10218
10219
10220
10221
10222
10223
10224 bool overwide_wrap_prefix =
10225 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
10226 && it->sp > 0 && it->method == GET_FROM_STRETCH
10227 && it->current_x >= it->last_visible_x
10228 && it->continuation_lines_width > 0
10229 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
10230
10231
10232 if (!overwide_wrap_prefix)
10233 set_iterator_to_next (it, true);
10234 if (IT_CHARPOS (*it) < CHARPOS (this_line_min_pos))
10235 SET_TEXT_POS (this_line_min_pos, IT_CHARPOS (*it), IT_BYTEPOS (*it));
10236 if (IT_CHARPOS (*it) < to_charpos)
10237 saw_smaller_pos = true;
10238 if (it->bidi_p
10239 && (op & MOVE_TO_POS)
10240 && IT_CHARPOS (*it) >= to_charpos
10241 && IT_CHARPOS (*it) < closest_pos)
10242 closest_pos = IT_CHARPOS (*it);
10243
10244
10245
10246 if (it->line_wrap == TRUNCATE
10247 && it->current_x >= it->last_visible_x)
10248 {
10249 if (!FRAME_WINDOW_P (it->f)
10250 || ((it->bidi_p && it->bidi_it.paragraph_dir == R2L)
10251 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
10252 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0
10253 || IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10254 {
10255 bool at_eob_p = false;
10256
10257 if ((at_eob_p = !get_next_display_element (it))
10258 || BUFFER_POS_REACHED_P ()
10259
10260
10261
10262
10263 || (it->bidi_p && (op & MOVE_TO_POS) != 0
10264 && !saw_smaller_pos
10265 && IT_CHARPOS (*it) > to_charpos))
10266 {
10267 if (it->bidi_p
10268 && !BUFFER_POS_REACHED_P ()
10269 && !at_eob_p && closest_pos < ZV)
10270 {
10271 RESTORE_IT (it, &ppos_it, ppos_data);
10272 if (closest_pos != to_charpos)
10273 move_it_in_display_line_to (it, closest_pos, -1,
10274 MOVE_TO_POS);
10275 }
10276 result = MOVE_POS_MATCH_OR_ZV;
10277 break;
10278 }
10279 if (ITERATOR_AT_END_OF_LINE_P (it))
10280 {
10281 result = MOVE_NEWLINE_OR_CR;
10282 break;
10283 }
10284 }
10285 else if (it->bidi_p && (op & MOVE_TO_POS) != 0
10286 && !saw_smaller_pos
10287 && IT_CHARPOS (*it) > to_charpos)
10288 {
10289 if (closest_pos < ZV)
10290 {
10291 RESTORE_IT (it, &ppos_it, ppos_data);
10292 if (closest_pos != to_charpos)
10293 move_it_in_display_line_to (it, closest_pos, -1,
10294 MOVE_TO_POS);
10295 }
10296 result = MOVE_POS_MATCH_OR_ZV;
10297 break;
10298 }
10299 result = MOVE_LINE_TRUNCATED;
10300 break;
10301 }
10302 #undef IT_RESET_X_ASCENT_DESCENT
10303 }
10304
10305 #undef BUFFER_POS_REACHED_P
10306
10307
10308
10309
10310
10311
10312 if (result == MOVE_LINE_CONTINUED
10313 && it->line_wrap == WORD_WRAP
10314 && wrap_it.sp >= 0
10315 && ((atpos_it.sp >= 0 && wrap_it.current_x < atpos_it.current_x)
10316 || (atx_it.sp >= 0 && wrap_it.current_x < atx_it.current_x)))
10317 RESTORE_IT (it, &wrap_it, wrap_data);
10318 else if (atpos_it.sp >= 0)
10319 RESTORE_IT (it, &atpos_it, atpos_data);
10320 else if (atx_it.sp >= 0)
10321 RESTORE_IT (it, &atx_it, atx_data);
10322
10323 done:
10324
10325 if (atpos_data)
10326 bidi_unshelve_cache (atpos_data, true);
10327 if (atx_data)
10328 bidi_unshelve_cache (atx_data, true);
10329 if (wrap_data)
10330 bidi_unshelve_cache (wrap_data, true);
10331 if (ppos_data)
10332 bidi_unshelve_cache (ppos_data, true);
10333
10334
10335
10336 it->glyph_row = saved_glyph_row;
10337 return result;
10338 }
10339
10340
10341 void
10342 move_it_in_display_line (struct it *it,
10343 ptrdiff_t to_charpos, int to_x,
10344 enum move_operation_enum op)
10345 {
10346 if (it->line_wrap == WORD_WRAP
10347 && (op & MOVE_TO_X))
10348 {
10349 struct it save_it;
10350 void *save_data = NULL;
10351 int skip;
10352
10353 SAVE_IT (save_it, *it, save_data);
10354 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10355
10356
10357
10358
10359 if (skip == MOVE_LINE_CONTINUED)
10360 {
10361 int prev_x = max (it->current_x - 1, 0);
10362 RESTORE_IT (it, &save_it, save_data);
10363 move_it_in_display_line_to
10364 (it, -1, prev_x, MOVE_TO_X);
10365 }
10366 else
10367 bidi_unshelve_cache (save_data, true);
10368 }
10369 else
10370 move_it_in_display_line_to (it, to_charpos, to_x, op);
10371 }
10372
10373
10374
10375
10376
10377
10378
10379
10380
10381
10382
10383
10384
10385
10386
10387
10388 int
10389 move_it_to (struct it *it, ptrdiff_t to_charpos, int to_x, int to_y, int to_vpos, int op)
10390 {
10391 enum move_it_result skip, skip2 = MOVE_X_REACHED;
10392 int line_height, line_start_x = 0, reached = 0;
10393 int max_current_x = 0;
10394 void *backup_data = NULL;
10395 ptrdiff_t orig_charpos = -1;
10396 enum it_method orig_method = NUM_IT_METHODS;
10397
10398 for (;;)
10399 {
10400 orig_charpos = IT_CHARPOS (*it);
10401 orig_method = it->method;
10402 if (op & MOVE_TO_VPOS)
10403 {
10404
10405
10406 if ((op & (MOVE_TO_X | MOVE_TO_POS)) == 0)
10407 {
10408 if (it->vpos == to_vpos)
10409 {
10410 reached = 1;
10411 break;
10412 }
10413 else
10414 skip = move_it_in_display_line_to (it, -1, -1, 0);
10415 }
10416 else
10417 {
10418
10419
10420 if (it->vpos == to_vpos)
10421 {
10422 reached = 2;
10423 break;
10424 }
10425
10426 skip = move_it_in_display_line_to (it, to_charpos, to_x, op);
10427
10428 if (skip == MOVE_POS_MATCH_OR_ZV || it->vpos == to_vpos)
10429 {
10430 reached = 3;
10431 break;
10432 }
10433 else if (skip == MOVE_X_REACHED && it->vpos != to_vpos)
10434 {
10435
10436 skip = move_it_in_display_line_to (it, to_charpos,
10437 -1, MOVE_TO_POS);
10438 if (skip == MOVE_POS_MATCH_OR_ZV)
10439 {
10440 reached = 4;
10441 break;
10442 }
10443 }
10444 }
10445 }
10446 else if (op & MOVE_TO_Y)
10447 {
10448 struct it it_backup;
10449
10450 if (it->line_wrap == WORD_WRAP)
10451 SAVE_IT (it_backup, *it, backup_data);
10452
10453
10454
10455
10456
10457
10458
10459
10460
10461
10462
10463
10464
10465 skip = move_it_in_display_line_to
10466 (it, to_charpos, ((op & MOVE_TO_X) ? to_x : 0),
10467 (MOVE_TO_X | (op & MOVE_TO_POS)));
10468
10469
10470 if (skip == MOVE_POS_MATCH_OR_ZV)
10471 reached = 5;
10472 else if (skip == MOVE_X_REACHED)
10473 {
10474
10475
10476
10477
10478 line_height = it->max_ascent + it->max_descent;
10479 if (to_y >= it->current_y
10480 && to_y < it->current_y + line_height)
10481 {
10482 reached = 6;
10483 break;
10484 }
10485 SAVE_IT (it_backup, *it, backup_data);
10486 move_trace ("move_it: from %td\n", IT_CHARPOS (*it));
10487 skip2 = move_it_in_display_line_to (it, to_charpos, -1,
10488 op & MOVE_TO_POS);
10489 move_trace ("move_it: to %td\n", IT_CHARPOS (*it));
10490 line_height = it->max_ascent + it->max_descent;
10491 move_trace ("move_it: line_height = %d\n", line_height);
10492
10493 if (to_y >= it->current_y
10494 && to_y < it->current_y + line_height)
10495 {
10496
10497
10498
10499
10500
10501
10502
10503
10504 int max_ascent = it->max_ascent;
10505 int max_descent = it->max_descent;
10506
10507 RESTORE_IT (it, &it_backup, backup_data);
10508 it->max_ascent = max_ascent;
10509 it->max_descent = max_descent;
10510 reached = 6;
10511 }
10512 else
10513 {
10514 skip = skip2;
10515 if (skip == MOVE_POS_MATCH_OR_ZV)
10516 {
10517 reached = 7;
10518
10519
10520
10521
10522
10523
10524
10525 if (to_charpos > 0
10526 && IT_CHARPOS (*it) != to_charpos
10527 && ((IT_CHARPOS (it_backup) > to_charpos)
10528 == (IT_CHARPOS (*it) > to_charpos)))
10529 {
10530 int max_ascent = it->max_ascent;
10531 int max_descent = it->max_descent;
10532
10533 RESTORE_IT (it, &it_backup, backup_data);
10534 it->max_ascent = max_ascent;
10535 it->max_descent = max_descent;
10536 }
10537 }
10538 }
10539 }
10540 else
10541 {
10542
10543 line_height = it->max_ascent + it->max_descent;
10544 move_trace ("move_it: line_height = %d\n", line_height);
10545
10546 if (to_y >= it->current_y
10547 && to_y < it->current_y + line_height)
10548 {
10549 if (to_y > it->current_y)
10550 max_current_x = max (it->current_x, max_current_x);
10551
10552
10553
10554
10555
10556 if (skip == MOVE_LINE_CONTINUED
10557 && it->line_wrap == WORD_WRAP)
10558 {
10559 int prev_x = max (it->current_x - 1, 0);
10560 RESTORE_IT (it, &it_backup, backup_data);
10561 skip = move_it_in_display_line_to
10562 (it, -1, prev_x, MOVE_TO_X);
10563 }
10564
10565 reached = 6;
10566 }
10567 }
10568
10569 if (reached)
10570 {
10571 max_current_x = max (it->current_x, max_current_x);
10572 break;
10573 }
10574 }
10575 else if (BUFFERP (it->object)
10576 && (it->method == GET_FROM_BUFFER
10577 || it->method == GET_FROM_STRETCH)
10578 && IT_CHARPOS (*it) >= to_charpos
10579
10580
10581
10582
10583
10584 && !(it->bidi_p
10585 && it->bidi_it.scan_dir == -1))
10586 skip = MOVE_POS_MATCH_OR_ZV;
10587 else
10588 skip = move_it_in_display_line_to (it, to_charpos, -1, MOVE_TO_POS);
10589
10590 switch (skip)
10591 {
10592 case MOVE_POS_MATCH_OR_ZV:
10593 max_current_x = max (it->current_x, max_current_x);
10594 reached = 8;
10595 goto out;
10596
10597 case MOVE_NEWLINE_OR_CR:
10598 max_current_x = max (it->current_x, max_current_x);
10599 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
10600 it->override_ascent = -1;
10601 set_iterator_to_next (it, true);
10602 it->continuation_lines_width = 0;
10603 break;
10604
10605 case MOVE_LINE_TRUNCATED:
10606 max_current_x = it->last_visible_x;
10607 it->continuation_lines_width = 0;
10608 reseat_at_next_visible_line_start (it, false);
10609 if ((op & MOVE_TO_POS) != 0
10610 && (IT_CHARPOS (*it) > to_charpos
10611 || (IT_CHARPOS (*it) == to_charpos
10612
10613
10614 && to_charpos == ZV
10615 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n')
10616
10617
10618
10619 && (it->sp == 0
10620 || (STRINGP (it->string)
10621 && (it->current.overlay_string_index < 0
10622 || (it->current.overlay_string_index >= 0
10623 && it->current.overlay_string_index
10624 >= it->n_overlay_strings - 1))
10625 && IT_STRING_CHARPOS (*it) >= it->end_charpos)))))
10626 {
10627 reached = 9;
10628 goto out;
10629 }
10630 break;
10631
10632 case MOVE_LINE_CONTINUED:
10633 max_current_x = it->last_visible_x;
10634
10635
10636
10637
10638 if (it->c == '\t')
10639 {
10640 it->continuation_lines_width += it->last_visible_x;
10641
10642
10643
10644 if (it->current_x != it->last_visible_x
10645 && (op & MOVE_TO_VPOS)
10646 && !(op & (MOVE_TO_X | MOVE_TO_POS)))
10647 {
10648 line_start_x = it->current_x + it->pixel_width
10649 - it->last_visible_x;
10650 if (FRAME_WINDOW_P (it->f))
10651 {
10652 struct face *face = FACE_FROM_ID (it->f, it->face_id);
10653 struct font *face_font = face->font;
10654
10655
10656
10657
10658
10659
10660
10661 eassert (face_font);
10662 if (face_font)
10663 {
10664 if (line_start_x < face_font->space_width)
10665 line_start_x
10666 += it->tab_width * face_font->space_width;
10667 }
10668 }
10669 set_iterator_to_next (it, false);
10670 }
10671 }
10672 else
10673 {
10674
10675
10676
10677
10678
10679
10680
10681
10682 if (IT_CHARPOS (*it) == orig_charpos
10683 && it->method == orig_method
10684 && orig_method == GET_FROM_BUFFER)
10685 set_iterator_to_next (it, false);
10686 it->continuation_lines_width += it->current_x;
10687 }
10688 break;
10689
10690 default:
10691 emacs_abort ();
10692 }
10693
10694
10695 it->current_x = line_start_x;
10696 line_start_x = 0;
10697 it->hpos = 0;
10698 it->line_number_produced_p = false;
10699 it->current_y += it->max_ascent + it->max_descent;
10700 ++it->vpos;
10701 last_height = it->max_ascent + it->max_descent;
10702 it->max_ascent = it->max_descent = 0;
10703 }
10704
10705 out:
10706
10707
10708
10709
10710
10711
10712 if (!FRAME_WINDOW_P (it->f)
10713 && op & MOVE_TO_POS
10714 && IT_CHARPOS (*it) == to_charpos
10715 && it->what == IT_CHARACTER
10716 && it->nglyphs > 1
10717 && it->line_wrap == WINDOW_WRAP
10718 && it->current_x == it->last_visible_x - 1
10719 && it->c != '\n'
10720 && it->c != '\t'
10721 && it->w->window_end_valid
10722 && it->vpos < it->w->window_end_vpos)
10723 {
10724 it->continuation_lines_width += it->current_x;
10725 it->current_x = it->hpos = it->max_ascent = it->max_descent = 0;
10726 it->current_y += it->max_ascent + it->max_descent;
10727 ++it->vpos;
10728 last_height = it->max_ascent + it->max_descent;
10729 }
10730
10731 if (backup_data)
10732 bidi_unshelve_cache (backup_data, true);
10733
10734 move_trace ("move_it_to: reached %d\n", reached);
10735
10736 return max_current_x;
10737 }
10738
10739
10740
10741
10742
10743
10744
10745
10746
10747
10748
10749 void
10750 move_it_vertically_backward (struct it *it, int dy)
10751 {
10752 int nlines, h;
10753 struct it it2, it3;
10754 void *it2data = NULL, *it3data = NULL;
10755 ptrdiff_t start_pos;
10756 int nchars_per_row
10757 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
10758 ptrdiff_t pos_limit;
10759
10760 move_further_back:
10761 eassert (dy >= 0);
10762
10763 start_pos = IT_CHARPOS (*it);
10764
10765
10766 nlines = max (1, dy / default_line_pixel_height (it->w));
10767 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
10768 pos_limit = BEGV;
10769 else
10770 pos_limit = max (start_pos - nlines * nchars_per_row, BEGV);
10771
10772
10773
10774
10775 while (nlines-- && IT_CHARPOS (*it) > pos_limit)
10776 back_to_previous_visible_line_start (it);
10777
10778
10779
10780
10781
10782 reseat_1 (it, it->current.pos, true);
10783
10784
10785 it->current_x = it->hpos = 0;
10786
10787 it->continuation_lines_width = 0;
10788
10789
10790
10791
10792
10793 SAVE_IT (it2, *it, it2data);
10794 it2.max_ascent = it2.max_descent = 0;
10795 do
10796 {
10797 move_it_to (&it2, start_pos, -1, -1, it2.vpos + 1,
10798 MOVE_TO_POS | MOVE_TO_VPOS);
10799 }
10800 while (!(IT_POS_VALID_AFTER_MOVE_P (&it2)
10801
10802
10803
10804
10805
10806
10807 || (it2.method == GET_FROM_STRING
10808 && IT_CHARPOS (it2) == start_pos
10809 && SREF (it2.string, IT_STRING_BYTEPOS (it2) - 1) == '\n')));
10810 eassert (IT_CHARPOS (*it) >= BEGV);
10811 SAVE_IT (it3, it2, it3data);
10812
10813 move_it_to (&it2, start_pos, -1, -1, -1, MOVE_TO_POS);
10814 eassert (IT_CHARPOS (*it) >= BEGV);
10815
10816
10817 h = it2.current_y - it->current_y;
10818
10819 nlines = it2.vpos - it->vpos;
10820
10821
10822
10823 it->vpos -= nlines;
10824 it->current_y -= h;
10825
10826 if (dy == 0)
10827 {
10828
10829
10830
10831 RESTORE_IT (it, it, it2data);
10832 if (nlines > 0)
10833 move_it_by_lines (it, nlines);
10834
10835
10836
10837
10838
10839
10840 if (it->bidi_p
10841 && !it->continuation_lines_width
10842 && !STRINGP (it->string)
10843 && IT_CHARPOS (*it) > BEGV
10844 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10845 {
10846 ptrdiff_t cp = IT_CHARPOS (*it), bp = IT_BYTEPOS (*it);
10847
10848 dec_both (&cp, &bp);
10849 SET_WITH_NARROWED_BEGV (it, cp,
10850 find_newline_no_quit (cp, bp, -1, NULL),
10851 get_small_narrowing_begv (it->w, IT_CHARPOS (*it)));
10852 move_it_to (it, cp, -1, -1, -1, MOVE_TO_POS);
10853 }
10854 bidi_unshelve_cache (it3data, true);
10855 }
10856 else
10857 {
10858
10859
10860 int target_y = it->current_y + h - dy;
10861 int y0 = it3.current_y;
10862 int y1;
10863 int line_height;
10864
10865 RESTORE_IT (&it3, &it3, it3data);
10866 y1 = line_bottom_y (&it3);
10867 line_height = y1 - y0;
10868 RESTORE_IT (it, it, it2data);
10869
10870
10871 if (target_y < it->current_y
10872
10873
10874
10875
10876 && (it->current_y - target_y
10877 > min (window_box_height (it->w), line_height * 2 / 3))
10878 && IT_CHARPOS (*it) > BEGV)
10879 {
10880 move_trace (" not far enough -> move_vert %d\n",
10881 target_y - it->current_y);
10882 dy = it->current_y - target_y;
10883 goto move_further_back;
10884 }
10885 else if (target_y >= it->current_y + line_height
10886 && IT_CHARPOS (*it) < ZV)
10887 {
10888
10889
10890
10891
10892
10893
10894
10895
10896 if (!FRAME_WINDOW_P (it->f))
10897 move_it_vertically (it, target_y - it->current_y);
10898 else
10899 {
10900 struct text_pos last_pos;
10901 int last_y, last_vpos;
10902 do
10903 {
10904 last_pos = it->current.pos;
10905 last_y = it->current_y;
10906 last_vpos = it->vpos;
10907 move_it_by_lines (it, 1);
10908 }
10909 while (target_y > it->current_y && IT_CHARPOS (*it) < ZV);
10910 if (it->current_y > target_y)
10911 {
10912 reseat (it, last_pos, true);
10913 it->current_y = last_y;
10914 it->vpos = last_vpos;
10915 }
10916 }
10917 }
10918 }
10919 }
10920
10921
10922
10923
10924
10925
10926 void
10927 move_it_vertically (struct it *it, int dy)
10928 {
10929 if (dy <= 0)
10930 move_it_vertically_backward (it, -dy);
10931 else
10932 {
10933 move_trace ("move_it_v: from %td, %d\n", IT_CHARPOS (*it), dy);
10934 move_it_to (it, ZV, -1, it->current_y + dy, -1,
10935 MOVE_TO_POS | MOVE_TO_Y);
10936 move_trace ("move_it_v: to %td\n", IT_CHARPOS (*it));
10937
10938
10939
10940 if (IT_CHARPOS (*it) == ZV
10941 && ZV > BEGV
10942 && FETCH_BYTE (IT_BYTEPOS (*it) - 1) != '\n')
10943 move_it_by_lines (it, 0);
10944 }
10945 }
10946
10947
10948
10949
10950 void
10951 move_it_past_eol (struct it *it)
10952 {
10953 enum move_it_result rc;
10954
10955 rc = move_it_in_display_line_to (it, Z, 0, MOVE_TO_POS);
10956 if (rc == MOVE_NEWLINE_OR_CR)
10957 set_iterator_to_next (it, false);
10958 }
10959
10960
10961
10962
10963
10964
10965
10966
10967
10968
10969 void
10970 move_it_by_lines (struct it *it, ptrdiff_t dvpos)
10971 {
10972
10973
10974
10975
10976
10977
10978
10979
10980
10981
10982
10983
10984
10985
10986
10987
10988
10989 if (dvpos == 0)
10990 {
10991
10992 move_it_vertically_backward (it, 0);
10993
10994 last_height = 0;
10995 }
10996 else if (dvpos > 0)
10997 {
10998 move_it_to (it, -1, -1, -1, it->vpos + dvpos, MOVE_TO_VPOS);
10999 if (!IT_POS_VALID_AFTER_MOVE_P (it))
11000 {
11001
11002
11003
11004
11005
11006
11007
11008
11009
11010
11011 move_it_to (it, IT_CHARPOS (*it) + it->string_from_display_prop_p,
11012 -1, -1, -1, MOVE_TO_POS);
11013 }
11014 }
11015 else
11016 {
11017 struct it it2;
11018 void *it2data = NULL;
11019 ptrdiff_t start_charpos, orig_charpos, i;
11020 int nchars_per_row
11021 = (it->last_visible_x - it->first_visible_x) / FRAME_COLUMN_WIDTH (it->f);
11022 bool hit_pos_limit = false;
11023 ptrdiff_t pos_limit;
11024
11025
11026
11027
11028 dvpos += it->vpos;
11029 orig_charpos = IT_CHARPOS (*it);
11030 move_it_vertically_backward (it, 0);
11031 dvpos -= it->vpos;
11032
11033
11034
11035 start_charpos = IT_CHARPOS (*it);
11036 if (it->line_wrap == TRUNCATE || nchars_per_row == 0)
11037 pos_limit = BEGV;
11038 else
11039 pos_limit = max (start_charpos + dvpos * nchars_per_row, BEGV);
11040
11041 for (i = -dvpos; i > 0 && IT_CHARPOS (*it) > pos_limit; --i)
11042 back_to_previous_visible_line_start (it);
11043 if (i > 0 && IT_CHARPOS (*it) <= pos_limit)
11044 hit_pos_limit = true;
11045 reseat (it, it->current.pos, true);
11046
11047
11048 while (!IT_POS_VALID_AFTER_MOVE_P (it))
11049 {
11050
11051 dvpos += it->vpos;
11052 move_it_vertically_backward (it, 0);
11053 dvpos -= it->vpos;
11054 if (IT_POS_VALID_AFTER_MOVE_P (it))
11055 break;
11056
11057
11058 back_to_previous_visible_line_start (it);
11059 reseat (it, it->current.pos, true);
11060 dvpos--;
11061 }
11062
11063 it->current_x = it->hpos = 0;
11064
11065
11066
11067 SAVE_IT (it2, *it, it2data);
11068 it2.vpos = it2.current_y = 0;
11069 move_it_to (&it2, start_charpos, -1, -1, -1, MOVE_TO_POS);
11070 it->vpos -= it2.vpos;
11071 it->current_y -= it2.current_y;
11072 it->current_x = it->hpos = 0;
11073
11074
11075 if (it2.vpos > -dvpos)
11076 {
11077 int delta = it2.vpos + dvpos;
11078
11079 RESTORE_IT (&it2, &it2, it2data);
11080 SAVE_IT (it2, *it, it2data);
11081 move_it_to (it, -1, -1, -1, it->vpos + delta, MOVE_TO_VPOS);
11082
11083
11084 if (it->vpos - it2.vpos > delta || IT_CHARPOS (*it) == orig_charpos)
11085 RESTORE_IT (it, &it2, it2data);
11086 else
11087 bidi_unshelve_cache (it2data, true);
11088 }
11089 else if (hit_pos_limit && pos_limit > BEGV
11090 && dvpos < 0 && it2.vpos < -dvpos)
11091 {
11092
11093
11094
11095
11096
11097
11098
11099
11100 dvpos += it2.vpos;
11101 RESTORE_IT (it, it, it2data);
11102 for (i = -dvpos; i > 0; --i)
11103 {
11104 back_to_previous_visible_line_start (it);
11105 it->vpos--;
11106 }
11107 reseat_1 (it, it->current.pos, true);
11108 }
11109 else
11110 RESTORE_IT (it, it, it2data);
11111 }
11112 }
11113
11114 int
11115 partial_line_height (struct it *it_origin)
11116 {
11117
11118
11119
11120
11121
11122 if (XBUFFER (it_origin->w->contents)->long_line_optimizations_p
11123 && it_origin->line_wrap == TRUNCATE)
11124 return 0;
11125
11126 int partial_height;
11127 void *it_data = NULL;
11128 struct it it;
11129 SAVE_IT (it, *it_origin, it_data);
11130 move_it_to (&it, ZV, -1, it.last_visible_y, -1,
11131 MOVE_TO_POS | MOVE_TO_Y);
11132 if (it.what == IT_EOB)
11133 {
11134 int vis_height = it.last_visible_y - it.current_y;
11135 int height = it.ascent + it.descent;
11136 partial_height = (vis_height < height) ? vis_height : 0;
11137 }
11138 else
11139 {
11140 int last_line_y = it.current_y;
11141 move_it_by_lines (&it, 1);
11142 partial_height = (it.current_y > it.last_visible_y)
11143 ? it.last_visible_y - last_line_y : 0;
11144 }
11145 RESTORE_IT (&it, &it, it_data);
11146 return partial_height;
11147 }
11148
11149
11150
11151
11152
11153
11154
11155
11156
11157
11158
11159
11160 static enum move_it_result
11161 fast_move_it_horizontally (struct it *it, ptrdiff_t nchars)
11162 {
11163 ptrdiff_t nl_bytepos;
11164 ptrdiff_t nl_pos = find_newline_no_quit (IT_CHARPOS (*it), IT_BYTEPOS (*it),
11165 1, &nl_bytepos);
11166 struct text_pos new_pos;
11167 enum move_it_result move_result;
11168
11169 if (nl_pos - IT_CHARPOS (*it) > nchars)
11170 {
11171 SET_TEXT_POS (new_pos,
11172 IT_CHARPOS (*it) + nchars,
11173 CHAR_TO_BYTE (IT_CHARPOS (*it) + nchars));
11174 move_result = MOVE_X_REACHED;
11175 }
11176 else
11177 {
11178 if (nl_bytepos < ZV_BYTE
11179 || (nl_bytepos > BEGV_BYTE
11180 && FETCH_BYTE (nl_bytepos - 1) == '\n'))
11181 {
11182 nl_pos--;
11183 nl_bytepos--;
11184 move_result = MOVE_NEWLINE_OR_CR;
11185 }
11186 else
11187 move_result = MOVE_POS_MATCH_OR_ZV;
11188 SET_TEXT_POS (new_pos, nl_pos, nl_bytepos);
11189 }
11190 reseat (it, new_pos, false);
11191 return move_result;
11192 }
11193
11194
11195
11196 bool
11197 in_display_vector_p (struct it *it)
11198 {
11199 return (it->method == GET_FROM_DISPLAY_VECTOR
11200 && it->current.dpvec_index > 0
11201 && it->dpvec + it->current.dpvec_index != it->dpend);
11202 }
11203
11204
11205
11206
11207
11208 static Lisp_Object
11209 window_text_pixel_size (Lisp_Object window, Lisp_Object from, Lisp_Object to,
11210 Lisp_Object x_limit, Lisp_Object y_limit,
11211 Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11212 {
11213 struct window *w = decode_live_window (window);
11214 struct it it;
11215 ptrdiff_t start, end, bpos;
11216 struct text_pos startp;
11217 void *itdata = NULL;
11218 int c, max_x = 0, max_y = 0, x = 0, y = 0, vertical_offset = 0, doff = 0;
11219
11220 if (NILP (from))
11221 {
11222 start = BEGV;
11223 bpos = BEGV_BYTE;
11224 }
11225 else if (EQ (from, Qt))
11226 {
11227 start = BEGV;
11228 bpos = BEGV_BYTE;
11229 while (bpos < ZV_BYTE)
11230 {
11231 c = FETCH_BYTE (bpos);
11232 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11233 break;
11234 inc_both (&start, &bpos);
11235 }
11236 while (bpos > BEGV_BYTE)
11237 {
11238 dec_both (&start, &bpos);
11239 c = FETCH_BYTE (bpos);
11240 if (!(c == ' ' || c == '\t'))
11241 break;
11242 }
11243 }
11244 else if (CONSP (from))
11245 {
11246 start = clip_to_bounds (BEGV, fix_position (XCAR (from)), ZV);
11247 bpos = CHAR_TO_BYTE (start);
11248 CHECK_FIXNUM (XCDR (from));
11249 vertical_offset = XFIXNUM (XCDR (from));
11250 }
11251 else
11252 {
11253 start = clip_to_bounds (BEGV, fix_position (from), ZV);
11254 bpos = CHAR_TO_BYTE (start);
11255 }
11256
11257 SET_TEXT_POS (startp, start, bpos);
11258
11259 if (NILP (to))
11260 end = ZV;
11261 else if (EQ (to, Qt))
11262 {
11263 end = ZV;
11264 bpos = ZV_BYTE;
11265 while (bpos > BEGV_BYTE)
11266 {
11267 dec_both (&end, &bpos);
11268 c = FETCH_BYTE (bpos);
11269 if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r'))
11270 {
11271 inc_both (&end, &bpos);
11272 break;
11273 }
11274 }
11275 while (bpos < ZV_BYTE)
11276 {
11277 c = fetch_char_advance (&end, &bpos);
11278 if (!(c == ' ' || c == '\t'))
11279 break;
11280 }
11281 }
11282 else
11283 end = clip_to_bounds (start, fix_position (to), ZV);
11284
11285 if (RANGED_FIXNUMP (0, x_limit, INT_MAX))
11286 max_x = XFIXNUM (x_limit);
11287 else if (!NILP (x_limit))
11288 max_x = INT_MAX;
11289
11290 if (NILP (y_limit))
11291 max_y = INT_MAX;
11292 else if (RANGED_FIXNUMP (0, y_limit, INT_MAX))
11293 max_y = XFIXNUM (y_limit);
11294
11295 itdata = bidi_shelve_cache ();
11296
11297 start_display (&it, w, startp);
11298
11299 int start_y = it.current_y;
11300
11301
11302
11303
11304
11305
11306
11307 it.bidi_p = false;
11308
11309 int start_x;
11310 if (vertical_offset != 0)
11311 {
11312 int last_y;
11313 it.current_y = 0;
11314
11315 move_it_by_lines (&it, 0);
11316
11317
11318
11319
11320
11321 if (vertical_offset < 0)
11322 {
11323 while (it.current_y > vertical_offset)
11324 {
11325 last_y = it.current_y;
11326 move_it_vertically_backward (&it,
11327 (abs (vertical_offset)
11328 + it.current_y));
11329
11330 if (it.current_y == last_y)
11331 break;
11332 }
11333 }
11334 else
11335 {
11336 move_it_vertically (&it, vertical_offset);
11337 }
11338
11339 it.current_y = (WINDOW_TAB_LINE_HEIGHT (w)
11340 + WINDOW_HEADER_LINE_HEIGHT (w));
11341 start = clip_to_bounds (BEGV, IT_CHARPOS (it), ZV);
11342 start_y = it.current_y;
11343 start_x = it.current_x;
11344 }
11345 else
11346 {
11347
11348
11349
11350 reseat_at_previous_visible_line_start (&it);
11351 it.current_x = it.hpos = 0;
11352 if (IT_CHARPOS (it) != start)
11353 {
11354 void *it1data = NULL;
11355 struct it it1;
11356
11357 SAVE_IT (it1, it, it1data);
11358 move_it_to (&it, start, -1, -1, -1, MOVE_TO_POS);
11359
11360
11361
11362
11363
11364 if (IT_CHARPOS (it) > start && start > BEGV)
11365 {
11366 ptrdiff_t it1pos = IT_CHARPOS (it1);
11367 int it1_x = it1.current_x;
11368
11369 RESTORE_IT (&it, &it1, it1data);
11370
11371
11372
11373
11374
11375 if (start - 1 > it1pos)
11376 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11377 else
11378 move_it_in_display_line (&it, start, it1_x + 1,
11379 MOVE_TO_POS | MOVE_TO_X);
11380 move_it_to (&it, start - 1, -1, -1, -1, MOVE_TO_POS);
11381 start_x = it.current_x;
11382
11383
11384
11385 if (IT_CHARPOS (it) == start - 1)
11386 start_x += it.pixel_width;
11387 }
11388 else
11389 {
11390 start_x = it.current_x;
11391 bidi_unshelve_cache (it1data, true);
11392 }
11393 }
11394 else
11395 start_x = it.current_x;
11396 }
11397
11398
11399 int move_op = MOVE_TO_POS | MOVE_TO_Y;
11400 int to_x = -1;
11401 it.current_y = start_y;
11402
11403
11404 if (FETCH_BYTE (start) == '\n')
11405 it.current_x = 0;
11406 if (!NILP (x_limit))
11407 {
11408 it.last_visible_x = max_x;
11409
11410
11411
11412 move_op |= MOVE_TO_X;
11413 to_x = INT_MAX;
11414 }
11415
11416 void *it2data = NULL;
11417 struct it it2;
11418 SAVE_IT (it2, it, it2data);
11419
11420 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11421
11422
11423
11424
11425
11426 if (IT_CHARPOS (it) > end)
11427 {
11428 end--;
11429 RESTORE_IT (&it, &it2, it2data);
11430 x = move_it_to (&it, end, to_x, max_y, -1, move_op);
11431
11432
11433
11434 if (IT_CHARPOS (it) == end)
11435 {
11436 x += it.pixel_width;
11437
11438
11439 if (!NILP (ignore_line_at_end))
11440 doff = (max (it.max_ascent, it.ascent)
11441 + max (it.max_descent, it.descent));
11442 else
11443 {
11444 it.max_ascent = max (it.max_ascent, it.ascent);
11445 it.max_descent = max (it.max_descent, it.descent);
11446 }
11447 }
11448 }
11449 else
11450 bidi_unshelve_cache (it2data, true);
11451
11452 if (!NILP (x_limit))
11453 {
11454
11455 if (x > max_x)
11456 x = max_x;
11457 }
11458
11459
11460
11461
11462 if (it.current_y > start_y)
11463 start_x = 0;
11464
11465
11466
11467 if (!NILP (ignore_line_at_end))
11468 y = (it.current_y + doff
11469 - WINDOW_TAB_LINE_HEIGHT (w)
11470 - WINDOW_HEADER_LINE_HEIGHT (w));
11471 else
11472 y = (it.current_y + it.max_ascent + it.max_descent + doff
11473 - WINDOW_TAB_LINE_HEIGHT (w) - WINDOW_HEADER_LINE_HEIGHT (w));
11474
11475
11476 if (y > max_y)
11477 y = max_y;
11478
11479 if ((EQ (mode_lines, Qtab_line) || EQ (mode_lines, Qt))
11480 && window_wants_tab_line (w))
11481
11482 {
11483 Lisp_Object window_tab_line_format
11484 = window_parameter (w, Qtab_line_format);
11485
11486 y = y + display_mode_line (w, TAB_LINE_FACE_ID,
11487 NILP (window_tab_line_format)
11488 ? BVAR (current_buffer, tab_line_format)
11489 : window_tab_line_format);
11490 }
11491
11492 if ((EQ (mode_lines, Qheader_line) || EQ (mode_lines, Qt))
11493 && window_wants_header_line (w))
11494 {
11495 Lisp_Object window_header_line_format
11496 = window_parameter (w, Qheader_line_format);
11497
11498 y = y + display_mode_line (w, HEADER_LINE_FACE_ID,
11499 NILP (window_header_line_format)
11500 ? BVAR (current_buffer, header_line_format)
11501 : window_header_line_format);
11502 }
11503
11504 if ((EQ (mode_lines, Qmode_line) || EQ (mode_lines, Qt))
11505 && window_wants_mode_line (w))
11506 {
11507 Lisp_Object window_mode_line_format
11508 = window_parameter (w, Qmode_line_format);
11509
11510 y = y + display_mode_line (w, CURRENT_MODE_LINE_ACTIVE_FACE_ID (w),
11511 NILP (window_mode_line_format)
11512 ? BVAR (current_buffer, mode_line_format)
11513 : window_mode_line_format);
11514 }
11515
11516 bidi_unshelve_cache (itdata, false);
11517
11518 return (!vertical_offset
11519 ? Fcons (make_fixnum (x - start_x), make_fixnum (y))
11520 : list3i (x - start_x, y, start));
11521 }
11522
11523 DEFUN ("window-text-pixel-size", Fwindow_text_pixel_size, Swindow_text_pixel_size, 0, 7, 0,
11524 doc:
11525
11526
11527
11528
11529
11530
11531
11532
11533
11534
11535
11536
11537
11538
11539
11540
11541
11542
11543
11544
11545
11546
11547
11548
11549
11550
11551
11552
11553
11554
11555
11556
11557
11558
11559
11560
11561
11562
11563
11564
11565
11566
11567
11568
11569
11570
11571
11572
11573
11574
11575
11576
11577
11578
11579 )
11580 (Lisp_Object window, Lisp_Object from, Lisp_Object to, Lisp_Object x_limit,
11581 Lisp_Object y_limit, Lisp_Object mode_lines, Lisp_Object ignore_line_at_end)
11582 {
11583 struct window *w = decode_live_window (window);
11584 struct buffer *b = XBUFFER (w->contents);
11585 struct buffer *old_b = NULL;
11586 Lisp_Object value;
11587
11588 if (b != current_buffer)
11589 {
11590 old_b = current_buffer;
11591 set_buffer_internal_1 (b);
11592 }
11593
11594 value = window_text_pixel_size (window, from, to, x_limit, y_limit, mode_lines,
11595 ignore_line_at_end);
11596
11597 if (old_b)
11598 set_buffer_internal_1 (old_b);
11599
11600 return value;
11601 }
11602
11603 DEFUN ("buffer-text-pixel-size", Fbuffer_text_pixel_size, Sbuffer_text_pixel_size, 0, 4, 0,
11604 doc:
11605
11606
11607
11608
11609
11610
11611
11612
11613
11614
11615
11616
11617 )
11618 (Lisp_Object buffer_or_name, Lisp_Object window, Lisp_Object x_limit,
11619 Lisp_Object y_limit)
11620 {
11621 struct window *w = decode_live_window (window);
11622 struct buffer *b = (NILP (buffer_or_name)
11623 ? current_buffer
11624 : XBUFFER (Fget_buffer (buffer_or_name)));
11625 Lisp_Object buffer, value;
11626 specpdl_ref count = SPECPDL_INDEX ();
11627
11628 XSETBUFFER (buffer, b);
11629
11630
11631
11632
11633 record_unwind_protect (unwind_with_echo_area_buffer,
11634 with_echo_area_buffer_unwind_data (w));
11635
11636 set_buffer_internal_1 (b);
11637
11638 if (!EQ (buffer, w->contents))
11639 {
11640 wset_buffer (w, buffer);
11641 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
11642 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
11643 }
11644
11645 value = window_text_pixel_size (window, Qnil, Qnil, x_limit, y_limit, Qnil,
11646 Qnil);
11647
11648 unbind_to (count, Qnil);
11649
11650 return value;
11651 }
11652
11653
11654 DEFUN ("display--line-is-continued-p", Fdisplay__line_is_continued_p,
11655 Sdisplay__line_is_continued_p, 0, 0, 0,
11656 doc: )
11657 (void)
11658 {
11659 struct buffer *oldb = current_buffer;
11660 struct window *w = XWINDOW (selected_window);
11661 enum move_it_result rc = MOVE_POS_MATCH_OR_ZV;
11662
11663 set_buffer_internal_1 (XBUFFER (w->contents));
11664
11665 if (PT < ZV)
11666 {
11667 struct text_pos startpos;
11668 struct it it;
11669 void *itdata;
11670
11671
11672 Lisp_Object opoint = Fpoint_marker ();
11673
11674
11675
11676 Fvertical_motion (make_fixnum (0), selected_window, Qnil);
11677 SET_TEXT_POS (startpos, PT, PT_BYTE);
11678 itdata = bidi_shelve_cache ();
11679 start_display (&it, w, startpos);
11680
11681 if (it.line_wrap != TRUNCATE)
11682 {
11683 it.glyph_row = NULL;
11684 rc = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
11685 }
11686 SET_PT_BOTH (marker_position (opoint), marker_byte_position (opoint));
11687 bidi_unshelve_cache (itdata, false);
11688 }
11689 set_buffer_internal_1 (oldb);
11690
11691 return rc == MOVE_LINE_CONTINUED ? Qt : Qnil;
11692 }
11693
11694
11695
11696
11697
11698
11699
11700
11701 static ptrdiff_t
11702 format_nargs (char const *format)
11703 {
11704 ptrdiff_t nargs = 0;
11705 for (char const *p = format; (p = strchr (p, '%')); p++)
11706 if (p[1] == '%')
11707 p++;
11708 else
11709 nargs++;
11710 return nargs;
11711 }
11712
11713
11714
11715
11716 void
11717 add_to_log (const char *format, ...)
11718 {
11719 va_list ap;
11720 va_start (ap, format);
11721 vadd_to_log (format, ap);
11722 va_end (ap);
11723 }
11724
11725 void
11726 vadd_to_log (char const *format, va_list ap)
11727 {
11728 ptrdiff_t form_nargs = format_nargs (format);
11729 ptrdiff_t nargs = 1 + form_nargs;
11730 Lisp_Object args[10];
11731 eassert (nargs <= ARRAYELTS (args));
11732 AUTO_STRING (args0, format);
11733 args[0] = args0;
11734 for (ptrdiff_t i = 1; i <= nargs; i++)
11735 args[i] = va_arg (ap, Lisp_Object);
11736 Lisp_Object msg = Qnil;
11737 msg = Fformat_message (nargs, args);
11738
11739 ptrdiff_t len = SBYTES (msg) + 1;
11740 USE_SAFE_ALLOCA;
11741 char *buffer = SAFE_ALLOCA (len);
11742 memcpy (buffer, SDATA (msg), len);
11743
11744 message_dolog (buffer, len - 1, true, STRING_MULTIBYTE (msg));
11745 SAFE_FREE ();
11746 }
11747
11748
11749
11750
11751 void
11752 message_log_maybe_newline (void)
11753 {
11754 if (message_log_need_newline)
11755 message_dolog ("", 0, true, false);
11756 }
11757
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768 void
11769 message_dolog (const char *m, ptrdiff_t nbytes, bool nlflag, bool multibyte)
11770 {
11771 const unsigned char *msg = (const unsigned char *) m;
11772
11773 if (!NILP (Vmemory_full))
11774 return;
11775
11776 if (!NILP (Vmessage_log_max))
11777 {
11778 struct buffer *oldbuf;
11779 Lisp_Object oldpoint, oldbegv, oldzv;
11780 int old_windows_or_buffers_changed = windows_or_buffers_changed;
11781 ptrdiff_t point_at_end = 0;
11782 ptrdiff_t zv_at_end = 0;
11783 Lisp_Object old_deactivate_mark;
11784
11785 old_deactivate_mark = Vdeactivate_mark;
11786 oldbuf = current_buffer;
11787
11788
11789
11790 if (! STRINGP (Vmessages_buffer_name))
11791 Vmessages_buffer_name = build_string ("*Messages*");
11792
11793
11794 bool newbuffer = NILP (Fget_buffer (Vmessages_buffer_name));
11795 Fset_buffer (Fget_buffer_create (Vmessages_buffer_name, Qnil));
11796 if (newbuffer
11797 && !NILP (Ffboundp (intern ("messages-buffer-mode"))))
11798 call0 (intern ("messages-buffer-mode"));
11799
11800 bset_undo_list (current_buffer, Qt);
11801 bset_cache_long_scans (current_buffer, Qnil);
11802
11803 oldpoint = message_dolog_marker1;
11804 set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);
11805 oldbegv = message_dolog_marker2;
11806 set_marker_restricted_both (oldbegv, Qnil, BEGV, BEGV_BYTE);
11807 oldzv = message_dolog_marker3;
11808 set_marker_restricted_both (oldzv, Qnil, ZV, ZV_BYTE);
11809
11810 if (PT == Z)
11811 point_at_end = 1;
11812 if (ZV == Z)
11813 zv_at_end = 1;
11814
11815 BEGV = BEG;
11816 BEGV_BYTE = BEG_BYTE;
11817 ZV = Z;
11818 ZV_BYTE = Z_BYTE;
11819 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11820
11821
11822
11823 if (multibyte
11824 && NILP (BVAR (current_buffer, enable_multibyte_characters)))
11825 {
11826
11827
11828 for (ptrdiff_t i = 0; i < nbytes; )
11829 {
11830 int char_bytes, c = check_char_and_length (msg + i, &char_bytes);
11831 char work = CHAR_TO_BYTE8 (c);
11832 insert_1_both (&work, 1, 1, true, false, false);
11833 i += char_bytes;
11834 }
11835 }
11836 else if (! multibyte
11837 && ! NILP (BVAR (current_buffer, enable_multibyte_characters)))
11838 {
11839
11840
11841 for (ptrdiff_t i = 0; i < nbytes; i++)
11842 {
11843 int c = make_char_multibyte (msg[i]);
11844 unsigned char str[MAX_MULTIBYTE_LENGTH];
11845 int char_bytes = CHAR_STRING (c, str);
11846 insert_1_both ((char *) str, 1, char_bytes, true, false, false);
11847 }
11848 }
11849 else if (nbytes)
11850 insert_1_both (m, chars_in_text (msg, nbytes), nbytes,
11851 true, false, false);
11852
11853 if (nlflag)
11854 {
11855 ptrdiff_t this_bol, this_bol_byte, prev_bol, prev_bol_byte;
11856 intmax_t dups;
11857
11858
11859
11860
11861
11862 specpdl_ref count = SPECPDL_INDEX ();
11863 specbind (Qinhibit_modification_hooks, Qt);
11864
11865 insert_1_both ("\n", 1, 1, true, false, false);
11866
11867 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, false);
11868 this_bol = PT;
11869 this_bol_byte = PT_BYTE;
11870
11871
11872
11873 if (this_bol > BEG)
11874 {
11875 scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, false);
11876 prev_bol = PT;
11877 prev_bol_byte = PT_BYTE;
11878
11879 dups = message_log_check_duplicate (prev_bol_byte,
11880 this_bol_byte);
11881 if (dups)
11882 {
11883 del_range_both (prev_bol, prev_bol_byte,
11884 this_bol, this_bol_byte, false);
11885 if (dups > 1)
11886 {
11887 char dupstr[sizeof " [ times]"
11888 + INT_STRLEN_BOUND (dups)];
11889
11890
11891
11892 int duplen = sprintf (dupstr, " [%"PRIdMAX" times]",
11893 dups);
11894 TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
11895 insert_1_both (dupstr, duplen, duplen,
11896 true, false, true);
11897 }
11898 }
11899 }
11900
11901
11902
11903
11904
11905 if (FIXNATP (Vmessage_log_max))
11906 {
11907 scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
11908 -XFIXNAT (Vmessage_log_max) - 1, false);
11909 del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, false);
11910 }
11911
11912 unbind_to (count, Qnil);
11913 }
11914 BEGV = marker_position (oldbegv);
11915 BEGV_BYTE = marker_byte_position (oldbegv);
11916
11917 if (zv_at_end)
11918 {
11919 ZV = Z;
11920 ZV_BYTE = Z_BYTE;
11921 }
11922 else
11923 {
11924 ZV = marker_position (oldzv);
11925 ZV_BYTE = marker_byte_position (oldzv);
11926 }
11927
11928 if (point_at_end)
11929 TEMP_SET_PT_BOTH (Z, Z_BYTE);
11930 else
11931
11932
11933 TEMP_SET_PT_BOTH (marker_position (oldpoint),
11934 marker_byte_position (oldpoint));
11935
11936 unchain_marker (XMARKER (oldpoint));
11937 unchain_marker (XMARKER (oldbegv));
11938 unchain_marker (XMARKER (oldzv));
11939
11940
11941
11942
11943
11944
11945
11946 windows_or_buffers_changed = old_windows_or_buffers_changed;
11947 bset_redisplay (current_buffer);
11948
11949 set_buffer_internal (oldbuf);
11950
11951 message_log_need_newline = !nlflag;
11952 Vdeactivate_mark = old_deactivate_mark;
11953 }
11954 }
11955
11956
11957
11958
11959
11960
11961
11962
11963 static intmax_t
11964 message_log_check_duplicate (ptrdiff_t prev_bol_byte, ptrdiff_t this_bol_byte)
11965 {
11966 ptrdiff_t i;
11967 ptrdiff_t len = Z_BYTE - 1 - this_bol_byte;
11968 bool seen_dots = false;
11969 unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
11970 unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
11971
11972 for (i = 0; i < len; i++)
11973 {
11974 if (i >= 3 && p1[i - 3] == '.' && p1[i - 2] == '.' && p1[i - 1] == '.')
11975 seen_dots = true;
11976 if (p1[i] != p2[i])
11977 return seen_dots;
11978 }
11979 p1 += len;
11980 if (*p1 == '\n')
11981 return 2;
11982 if (*p1++ == ' ' && *p1++ == '[')
11983 {
11984 char *pend;
11985 intmax_t n = strtoimax ((char *) p1, &pend, 10);
11986 if (0 < n && n < INTMAX_MAX && strncmp (pend, " times]\n", 8) == 0)
11987 return n + 1;
11988 }
11989 return 0;
11990 }
11991
11992
11993
11994
11995
11996
11997
11998
11999
12000 void
12001 message3 (Lisp_Object m)
12002 {
12003 clear_message (true, true);
12004 cancel_echoing ();
12005
12006
12007 message_log_maybe_newline ();
12008 if (STRINGP (m))
12009 {
12010 ptrdiff_t nbytes = SBYTES (m);
12011 bool multibyte = STRING_MULTIBYTE (m);
12012 char *buffer;
12013 USE_SAFE_ALLOCA;
12014 SAFE_ALLOCA_STRING (buffer, m);
12015 message_dolog (buffer, nbytes, true, multibyte);
12016 SAFE_FREE ();
12017 }
12018 if (! inhibit_message)
12019 message3_nolog (m);
12020 }
12021
12022
12023
12024 static void
12025 message_to_stderr (Lisp_Object m)
12026 {
12027 if (noninteractive_need_newline)
12028 {
12029 noninteractive_need_newline = false;
12030 errputc ('\n');
12031 }
12032 if (STRINGP (m))
12033 {
12034 Lisp_Object coding_system = Vlocale_coding_system;
12035 Lisp_Object s;
12036
12037 if (!NILP (Vcoding_system_for_write))
12038 coding_system = Vcoding_system_for_write;
12039 if (!NILP (coding_system))
12040 s = code_convert_string_norecord (m, coding_system, true);
12041 else
12042 s = m;
12043
12044 errwrite (SDATA (s), SBYTES (s));
12045 }
12046 if (STRINGP (m) || !cursor_in_echo_area)
12047 errputc ('\n');
12048 }
12049
12050
12051
12052
12053
12054
12055 void
12056 message3_nolog (Lisp_Object m)
12057 {
12058 struct frame *sf = SELECTED_FRAME ();
12059
12060 if (FRAME_INITIAL_P (sf))
12061 message_to_stderr (m);
12062
12063
12064
12065 else if (INTERACTIVE && sf->glyphs_initialized_p)
12066 {
12067
12068
12069 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
12070 Lisp_Object frame = XWINDOW (mini_window)->frame;
12071 struct frame *f = XFRAME (frame);
12072
12073 if (FRAME_VISIBLE_P (sf) && !FRAME_VISIBLE_P (f))
12074 Fmake_frame_visible (frame);
12075
12076 if (STRINGP (m) && SCHARS (m) > 0)
12077 {
12078 set_message (m);
12079 if (minibuffer_auto_raise)
12080 Fraise_frame (frame);
12081
12082
12083 echo_message_buffer = Qnil;
12084 }
12085 else
12086 clear_message (true, true);
12087
12088 do_pending_window_change (false);
12089 echo_area_display (true);
12090 do_pending_window_change (false);
12091 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
12092 (*FRAME_TERMINAL (f)->frame_up_to_date_hook) (f);
12093 }
12094 }
12095
12096
12097
12098
12099
12100
12101
12102
12103
12104
12105 void
12106 message1 (const char *m)
12107 {
12108 message3 (m ? build_unibyte_string (m) : Qnil);
12109 }
12110
12111
12112
12113
12114 void
12115 message1_nolog (const char *m)
12116 {
12117 message3_nolog (m ? build_unibyte_string (m) : Qnil);
12118 }
12119
12120
12121
12122
12123 void
12124 message_with_string (const char *m, Lisp_Object string, bool log)
12125 {
12126 CHECK_STRING (string);
12127
12128 bool need_message;
12129 if (noninteractive)
12130 need_message = !!m;
12131 else if (!INTERACTIVE)
12132 need_message = false;
12133 else
12134 {
12135
12136
12137
12138 Lisp_Object mini_window;
12139 struct frame *f, *sf = SELECTED_FRAME ();
12140
12141
12142
12143 mini_window = FRAME_MINIBUF_WINDOW (sf);
12144 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12145
12146
12147
12148
12149 need_message = f->glyphs_initialized_p;
12150 }
12151
12152 if (need_message)
12153 {
12154 AUTO_STRING (fmt, m);
12155 Lisp_Object msg = CALLN (Fformat_message, fmt, string);
12156
12157 if (noninteractive)
12158 message_to_stderr (msg);
12159 else
12160 {
12161 if (log)
12162 message3 (msg);
12163 else
12164 message3_nolog (msg);
12165
12166
12167
12168 message_buf_print = false;
12169 }
12170 }
12171 }
12172
12173
12174
12175
12176
12177
12178
12179
12180
12181
12182
12183
12184 static void ATTRIBUTE_FORMAT_PRINTF (1, 0)
12185 vmessage (const char *m, va_list ap)
12186 {
12187 if (noninteractive)
12188 {
12189 if (m)
12190 {
12191 if (noninteractive_need_newline)
12192 putc ('\n', stderr);
12193 noninteractive_need_newline = false;
12194 vfprintf (stderr, m, ap);
12195 if (!cursor_in_echo_area)
12196 putc ('\n', stderr);
12197 fflush (stderr);
12198 }
12199 }
12200 else if (INTERACTIVE)
12201 {
12202
12203
12204
12205 Lisp_Object mini_window;
12206 struct frame *f, *sf = SELECTED_FRAME ();
12207
12208
12209
12210 mini_window = FRAME_MINIBUF_WINDOW (sf);
12211 f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
12212
12213
12214
12215
12216 if (f->glyphs_initialized_p)
12217 {
12218 if (m)
12219 {
12220 ptrdiff_t len;
12221 ptrdiff_t maxsize = FRAME_MESSAGE_BUF_SIZE (f);
12222 USE_SAFE_ALLOCA;
12223 char *message_buf = SAFE_ALLOCA (maxsize + 1);
12224
12225 len = doprnt (message_buf, maxsize, m, 0, ap);
12226
12227 message3 (make_string (message_buf, len));
12228 SAFE_FREE ();
12229 }
12230 else
12231 message1 (0);
12232
12233
12234
12235 message_buf_print = false;
12236 }
12237 }
12238 }
12239
12240
12241 void
12242 message (const char *m, ...)
12243 {
12244 va_list ap;
12245 va_start (ap, m);
12246 vmessage (m, ap);
12247 va_end (ap);
12248 }
12249
12250
12251
12252
12253
12254
12255 void
12256 update_echo_area (void)
12257 {
12258 if (!NILP (echo_area_buffer[0]))
12259 {
12260 Lisp_Object string;
12261 string = Fcurrent_message ();
12262 message3 (string);
12263 }
12264 }
12265
12266
12267
12268
12269
12270 static void
12271 ensure_echo_area_buffers (void)
12272 {
12273 for (int i = 0; i < 2; i++)
12274 if (!BUFFERP (echo_buffer[i])
12275 || !BUFFER_LIVE_P (XBUFFER (echo_buffer[i])))
12276 {
12277 Lisp_Object old_buffer = echo_buffer[i];
12278 static char const name_fmt[] = " *Echo Area %d*";
12279 char name[sizeof name_fmt + INT_STRLEN_BOUND (int)];
12280 AUTO_STRING_WITH_LEN (lname, name, sprintf (name, name_fmt, i));
12281 echo_buffer[i] = Fget_buffer_create (lname, Qnil);
12282 bset_truncate_lines (XBUFFER (echo_buffer[i]), Qnil);
12283
12284
12285
12286
12287 for (int j = 0; j < 2; j++)
12288 if (EQ (old_buffer, echo_area_buffer[j]))
12289 echo_area_buffer[j] = echo_buffer[i];
12290 }
12291 }
12292
12293
12294
12295
12296
12297
12298
12299
12300
12301
12302
12303
12304
12305
12306
12307
12308
12309
12310 static bool
12311 with_echo_area_buffer (struct window *w, int which,
12312 bool (*fn) (void *, Lisp_Object),
12313 void *a1, Lisp_Object a2)
12314 {
12315 Lisp_Object buffer;
12316 bool this_one, the_other, clear_buffer_p, rc;
12317 specpdl_ref count = SPECPDL_INDEX ();
12318
12319
12320 ensure_echo_area_buffers ();
12321
12322 clear_buffer_p = false;
12323
12324 if (which == 0)
12325 this_one = false, the_other = true;
12326 else if (which > 0)
12327 this_one = true, the_other = false;
12328 else
12329 {
12330 this_one = false, the_other = true;
12331 clear_buffer_p = true;
12332
12333
12334
12335 if (!NILP (echo_area_buffer[this_one])
12336 && EQ (echo_area_buffer[this_one], echo_area_buffer[the_other]))
12337 echo_area_buffer[this_one] = Qnil;
12338 }
12339
12340
12341
12342 if (NILP (echo_area_buffer[this_one]))
12343 {
12344 echo_area_buffer[this_one]
12345 = (EQ (echo_area_buffer[the_other], echo_buffer[this_one])
12346 ? echo_buffer[the_other]
12347 : echo_buffer[this_one]);
12348 clear_buffer_p = true;
12349 }
12350
12351 buffer = echo_area_buffer[this_one];
12352
12353
12354
12355 if (echo_kboard == NULL && EQ (buffer, echo_message_buffer))
12356 cancel_echoing ();
12357
12358 record_unwind_protect (unwind_with_echo_area_buffer,
12359 with_echo_area_buffer_unwind_data (w));
12360
12361
12362
12363
12364
12365
12366
12367
12368 set_buffer_internal_1 (XBUFFER (buffer));
12369 if (w)
12370 {
12371 wset_buffer (w, buffer);
12372 set_marker_both (w->pointm, buffer, BEG, BEG_BYTE);
12373 set_marker_both (w->old_pointm, buffer, BEG, BEG_BYTE);
12374 }
12375
12376 bset_undo_list (current_buffer, Qt);
12377 bset_read_only (current_buffer, Qnil);
12378 specbind (Qinhibit_read_only, Qt);
12379 specbind (Qinhibit_modification_hooks, Qt);
12380
12381 if (clear_buffer_p && Z > BEG)
12382 del_range (BEG, Z);
12383
12384 eassert (BEGV >= BEG);
12385 eassert (ZV <= Z && ZV >= BEGV);
12386
12387 rc = fn (a1, a2);
12388
12389 eassert (BEGV >= BEG);
12390 eassert (ZV <= Z && ZV >= BEGV);
12391
12392 unbind_to (count, Qnil);
12393 return rc;
12394 }
12395
12396
12397
12398
12399
12400 static Lisp_Object
12401 with_echo_area_buffer_unwind_data (struct window *w)
12402 {
12403 int i = 0;
12404 Lisp_Object vector, tmp;
12405
12406
12407
12408 vector = Vwith_echo_area_save_vector;
12409 Vwith_echo_area_save_vector = Qnil;
12410
12411 if (NILP (vector))
12412 vector = make_nil_vector (11);
12413
12414 XSETBUFFER (tmp, current_buffer); ASET (vector, i, tmp); ++i;
12415 ASET (vector, i, Vdeactivate_mark); ++i;
12416 ASET (vector, i, make_fixnum (windows_or_buffers_changed)); ++i;
12417
12418 if (w)
12419 {
12420 XSETWINDOW (tmp, w); ASET (vector, i, tmp); ++i;
12421 ASET (vector, i, w->contents); ++i;
12422 ASET (vector, i, make_fixnum (marker_position (w->pointm))); ++i;
12423 ASET (vector, i, make_fixnum (marker_byte_position (w->pointm))); ++i;
12424 ASET (vector, i, make_fixnum (marker_position (w->old_pointm))); ++i;
12425 ASET (vector, i, make_fixnum (marker_byte_position (w->old_pointm))); ++i;
12426 ASET (vector, i, make_fixnum (marker_position (w->start))); ++i;
12427 ASET (vector, i, make_fixnum (marker_byte_position (w->start))); ++i;
12428 }
12429 else
12430 {
12431 int end = i + 8;
12432 for (; i < end; ++i)
12433 ASET (vector, i, Qnil);
12434 }
12435
12436 eassert (i == ASIZE (vector));
12437 return vector;
12438 }
12439
12440
12441
12442
12443
12444 static void
12445 unwind_with_echo_area_buffer (Lisp_Object vector)
12446 {
12447 set_buffer_internal_1 (XBUFFER (AREF (vector, 0)));
12448 Vdeactivate_mark = AREF (vector, 1);
12449 windows_or_buffers_changed = XFIXNAT (AREF (vector, 2));
12450
12451 if (WINDOWP (AREF (vector, 3)))
12452 {
12453 struct window *w;
12454 Lisp_Object buffer;
12455
12456 w = XWINDOW (AREF (vector, 3));
12457 buffer = AREF (vector, 4);
12458
12459 wset_buffer (w, buffer);
12460 set_marker_restricted_both (w->pointm, buffer,
12461 XFIXNAT (AREF (vector, 5)),
12462 XFIXNAT (AREF (vector, 6)));
12463 set_marker_restricted_both (w->old_pointm, buffer,
12464 XFIXNAT (AREF (vector, 7)),
12465 XFIXNAT (AREF (vector, 8)));
12466 set_marker_restricted_both (w->start, buffer,
12467 XFIXNAT (AREF (vector, 9)),
12468 XFIXNAT (AREF (vector, 10)));
12469 }
12470
12471 Vwith_echo_area_save_vector = vector;
12472 }
12473
12474
12475
12476
12477
12478 void
12479 setup_echo_area_for_printing (bool multibyte_p)
12480 {
12481
12482 if (! FRAME_LIVE_P (XFRAME (selected_frame)))
12483 Fkill_emacs (Qnil, Qnil);
12484
12485 ensure_echo_area_buffers ();
12486
12487 if (!message_buf_print)
12488 {
12489
12490
12491 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12492 echo_area_buffer[0] = echo_buffer[1];
12493 else
12494 echo_area_buffer[0] = echo_buffer[0];
12495
12496
12497 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12498 bset_truncate_lines (current_buffer, Qnil);
12499
12500 if (Z > BEG)
12501 {
12502 specpdl_ref count = SPECPDL_INDEX ();
12503 specbind (Qinhibit_read_only, Qt);
12504
12505 del_range (BEG, Z);
12506 unbind_to (count, Qnil);
12507 }
12508 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
12509
12510
12511
12512
12513
12514
12515
12516 if (unibyte_display_via_language_environment
12517 && !multibyte_p
12518 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
12519 Fset_buffer_multibyte (Qnil);
12520 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
12521 Fset_buffer_multibyte (Qt);
12522
12523
12524 if (minibuffer_auto_raise)
12525 {
12526 struct frame *sf = SELECTED_FRAME ();
12527 Lisp_Object mini_window;
12528 mini_window = FRAME_MINIBUF_WINDOW (sf);
12529 Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
12530 }
12531
12532 message_log_maybe_newline ();
12533 message_buf_print = true;
12534 }
12535 else
12536 {
12537 if (NILP (echo_area_buffer[0]))
12538 {
12539 if (EQ (echo_area_buffer[1], echo_buffer[0]))
12540 echo_area_buffer[0] = echo_buffer[1];
12541 else
12542 echo_area_buffer[0] = echo_buffer[0];
12543 }
12544
12545 if (current_buffer != XBUFFER (echo_area_buffer[0]))
12546 {
12547
12548 set_buffer_internal (XBUFFER (echo_area_buffer[0]));
12549 bset_truncate_lines (current_buffer, Qnil);
12550 }
12551 }
12552 }
12553
12554
12555
12556
12557
12558
12559
12560 static bool
12561 display_echo_area (struct window *w)
12562 {
12563 bool no_message_p, window_height_changed_p;
12564
12565
12566
12567
12568
12569
12570 specpdl_ref count = inhibit_garbage_collection ();
12571
12572
12573
12574
12575
12576 bool i = display_last_displayed_message_p;
12577
12578
12579
12580 no_message_p = NILP (echo_area_buffer[i]);
12581
12582 window_height_changed_p
12583 = with_echo_area_buffer (w, display_last_displayed_message_p,
12584 display_echo_area_1, w, Qnil);
12585
12586 if (no_message_p)
12587 echo_area_buffer[i] = Qnil;
12588
12589 unbind_to (count, Qnil);
12590 return window_height_changed_p;
12591 }
12592
12593
12594
12595
12596
12597
12598
12599
12600 static bool
12601 display_echo_area_1 (void *a1, Lisp_Object a2)
12602 {
12603 struct window *w = a1;
12604 Lisp_Object window;
12605 struct text_pos start;
12606
12607
12608
12609
12610 forget_escape_and_glyphless_faces ();
12611
12612
12613
12614
12615 bool window_height_changed_p = resize_mini_window (w, false);
12616
12617
12618 SET_TEXT_POS_FROM_MARKER (start, w->start);
12619
12620
12621 clear_glyph_matrix (w->desired_matrix);
12622 XSETWINDOW (window, w);
12623 void *itdata = bidi_shelve_cache ();
12624 try_window (window, start, 0);
12625 bidi_unshelve_cache (itdata, false);
12626
12627 return window_height_changed_p;
12628 }
12629
12630
12631
12632
12633
12634
12635 void
12636 resize_echo_area_exactly (void)
12637 {
12638 if (BUFFERP (echo_area_buffer[0])
12639 && WINDOWP (echo_area_window))
12640 {
12641 struct window *w = XWINDOW (echo_area_window);
12642 Lisp_Object resize_exactly = (minibuf_level == 0 ? Qt : Qnil);
12643 bool resized_p = with_echo_area_buffer (w, 0, resize_mini_window_1,
12644 w, resize_exactly);
12645 if (resized_p)
12646 {
12647 windows_or_buffers_changed = 42;
12648 update_mode_lines = 30;
12649 redisplay_internal ();
12650 }
12651 }
12652 }
12653
12654
12655
12656
12657
12658
12659
12660
12661 static bool
12662 resize_mini_window_1 (void *a1, Lisp_Object exactly)
12663 {
12664 return resize_mini_window (a1, !NILP (exactly));
12665 }
12666
12667
12668
12669
12670
12671
12672
12673
12674
12675
12676
12677
12678
12679 bool
12680 resize_mini_window (struct window *w, bool exact_p)
12681 {
12682 struct frame *f = XFRAME (w->frame);
12683 int old_height = WINDOW_BOX_TEXT_HEIGHT (w);
12684
12685 eassert (MINI_WINDOW_P (w));
12686
12687
12688
12689
12690
12691
12692
12693 if (!NILP (Vinhibit_redisplay))
12694 return false;
12695
12696
12697 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12698 set_marker_both (w->start, w->contents,
12699 BUF_BEGV (XBUFFER (w->contents)),
12700 BUF_BEGV_BYTE (XBUFFER (w->contents)));
12701
12702
12703 if ((NILP (Vresize_mini_windows)
12704 && (NILP (resize_mini_frames) || !FRAME_MINIBUF_ONLY_P (f)))
12705 || (FRAME_X_P (f) && FRAME_OUTPUT_DATA (f) == NULL))
12706 return false;
12707
12708 if (FRAME_MINIBUF_ONLY_P (f))
12709 {
12710 if (!NILP (resize_mini_frames))
12711 safe_call1 (Qwindow__resize_mini_frame, WINDOW_FRAME (w));
12712 }
12713 else
12714 {
12715 struct it it;
12716 int unit = FRAME_LINE_HEIGHT (f);
12717 int height, max_height;
12718 struct text_pos start;
12719 struct buffer *old_current_buffer = NULL;
12720 int windows_height = FRAME_INNER_HEIGHT (f);
12721
12722 if (current_buffer != XBUFFER (w->contents))
12723 {
12724 old_current_buffer = current_buffer;
12725 set_buffer_internal (XBUFFER (w->contents));
12726 }
12727
12728 init_iterator (&it, w, BEGV, BEGV_BYTE, NULL, DEFAULT_FACE_ID);
12729
12730
12731 if (FLOATP (Vmax_mini_window_height))
12732 max_height = XFLOAT_DATA (Vmax_mini_window_height) * windows_height;
12733 else if (FIXNUMP (Vmax_mini_window_height))
12734 max_height = XFIXNUM (Vmax_mini_window_height) * unit;
12735 else
12736 max_height = windows_height / 4;
12737
12738
12739 max_height = clip_to_bounds (unit, max_height, windows_height);
12740
12741
12742 last_height = 0;
12743 move_it_to (&it, ZV, -1, -1, -1, MOVE_TO_POS);
12744
12745
12746 if (it.max_ascent == 0 && it.max_descent == 0)
12747 {
12748 height = it.current_y;
12749
12750
12751
12752
12753
12754 if (!(it.line_wrap == TRUNCATE
12755 && it.current_x <= it.first_visible_x
12756 && ZV_BYTE > 1
12757 && FETCH_BYTE (ZV_BYTE - 1) != '\n'))
12758 height += last_height;
12759 }
12760 else
12761 height = it.current_y + it.max_ascent + it.max_descent;
12762 height -= min (it.extra_line_spacing, it.max_extra_line_spacing);
12763
12764
12765 if (height > max_height)
12766 {
12767 height = (max_height / unit) * unit;
12768 if (redisplay_adhoc_scroll_in_resize_mini_windows)
12769 {
12770 init_iterator (&it, w, ZV, ZV_BYTE, NULL, DEFAULT_FACE_ID);
12771 move_it_vertically_backward (&it, height - unit);
12772
12773
12774
12775
12776
12777
12778
12779
12780
12781 move_it_by_lines (&it, 0);
12782 start = it.current.pos;
12783
12784
12785 w->start_at_line_beg = false;
12786 SET_MARKER_FROM_TEXT_POS (w->start, start);
12787 }
12788 }
12789 else
12790 {
12791 SET_TEXT_POS (start, BEGV, BEGV_BYTE);
12792 SET_MARKER_FROM_TEXT_POS (w->start, start);
12793 }
12794
12795 if (EQ (Vresize_mini_windows, Qgrow_only))
12796 {
12797
12798
12799 if (height > old_height)
12800 grow_mini_window (w, height - old_height);
12801 else if (height < old_height && (exact_p || BEGV == ZV))
12802 shrink_mini_window (w);
12803 }
12804 else if (height != old_height)
12805
12806 grow_mini_window (w, height - old_height);
12807
12808 if (old_current_buffer)
12809 set_buffer_internal (old_current_buffer);
12810 }
12811
12812 return WINDOW_BOX_TEXT_HEIGHT (w) != old_height;
12813 }
12814
12815
12816
12817
12818
12819 Lisp_Object
12820 current_message (void)
12821 {
12822 Lisp_Object msg;
12823
12824 if (!BUFFERP (echo_area_buffer[0]))
12825 msg = Qnil;
12826 else
12827 {
12828 with_echo_area_buffer (0, 0, current_message_1, &msg, Qnil);
12829 if (NILP (msg))
12830 echo_area_buffer[0] = Qnil;
12831 }
12832
12833 return msg;
12834 }
12835
12836
12837 static bool
12838 current_message_1 (void *a1, Lisp_Object a2)
12839 {
12840 Lisp_Object *msg = a1;
12841
12842 if (Z > BEG)
12843 *msg = make_buffer_string (BEG, Z, true);
12844 else
12845 *msg = Qnil;
12846 return false;
12847 }
12848
12849
12850
12851
12852
12853
12854
12855 bool
12856 push_message (void)
12857 {
12858 Lisp_Object msg = current_message ();
12859 Vmessage_stack = Fcons (msg, Vmessage_stack);
12860 return STRINGP (msg);
12861 }
12862
12863
12864
12865
12866 void
12867 restore_message (void)
12868 {
12869 eassert (CONSP (Vmessage_stack));
12870 message3_nolog (XCAR (Vmessage_stack));
12871 }
12872
12873
12874
12875
12876 void
12877 pop_message_unwind (void)
12878 {
12879
12880 eassert (CONSP (Vmessage_stack));
12881 Vmessage_stack = XCDR (Vmessage_stack);
12882 }
12883
12884
12885
12886
12887
12888
12889 void
12890 check_message_stack (void)
12891 {
12892 if (!NILP (Vmessage_stack))
12893 emacs_abort ();
12894 }
12895
12896 void
12897 clear_message_stack (void)
12898 {
12899 Vmessage_stack = Qnil;
12900 }
12901
12902
12903
12904
12905 void
12906 truncate_echo_area (ptrdiff_t nchars)
12907 {
12908 if (nchars == 0)
12909 echo_area_buffer[0] = Qnil;
12910 else if (!noninteractive
12911 && INTERACTIVE
12912 && !NILP (echo_area_buffer[0]))
12913 {
12914 struct frame *sf = SELECTED_FRAME ();
12915
12916
12917
12918 if (sf->glyphs_initialized_p)
12919 with_echo_area_buffer (0, 0, truncate_message_1,
12920 (void *) (intptr_t) nchars, Qnil);
12921 }
12922 }
12923
12924
12925
12926
12927
12928 static bool
12929 truncate_message_1 (void *a1, Lisp_Object a2)
12930 {
12931 intptr_t nchars = (intptr_t) a1;
12932 if (BEG + nchars < Z)
12933 del_range (BEG + nchars, Z);
12934 if (Z == BEG)
12935 echo_area_buffer[0] = Qnil;
12936 return false;
12937 }
12938
12939 extern intptr_t garbage_collection_inhibited;
12940
12941
12942
12943 static void
12944 set_message (Lisp_Object string)
12945 {
12946 Lisp_Object message = Qnil;
12947
12948 eassert (STRINGP (string));
12949
12950 if (FUNCTIONP (Vset_message_function)
12951
12952
12953
12954 && !garbage_collection_inhibited)
12955 {
12956 specpdl_ref count = SPECPDL_INDEX ();
12957 specbind (Qinhibit_quit, Qt);
12958 message = safe_call1 (Vset_message_function, string);
12959 unbind_to (count, Qnil);
12960
12961 if (STRINGP (message))
12962 {
12963 string = message;
12964 message = Qnil;
12965 }
12966 }
12967
12968 if (NILP (message))
12969 {
12970 message_enable_multibyte = STRING_MULTIBYTE (string);
12971
12972 with_echo_area_buffer (0, -1, set_message_1, 0, string);
12973 message_buf_print = false;
12974 help_echo_showing_p = false;
12975 }
12976
12977 if (STRINGP (Vdebug_on_message)
12978 && STRINGP (string)
12979 && fast_string_match (Vdebug_on_message, string) >= 0)
12980 call_debugger (list2 (Qerror, string));
12981 }
12982
12983
12984
12985
12986
12987
12988 static bool
12989 set_message_1 (void *a1, Lisp_Object string)
12990 {
12991 eassert (STRINGP (string));
12992
12993
12994
12995
12996
12997
12998 if (!message_enable_multibyte
12999 && unibyte_display_via_language_environment
13000 && !NILP (BVAR (current_buffer, enable_multibyte_characters)))
13001 Fset_buffer_multibyte (Qnil);
13002 else if (NILP (BVAR (current_buffer, enable_multibyte_characters)))
13003 Fset_buffer_multibyte (Qt);
13004
13005 bset_truncate_lines (current_buffer, message_truncate_lines ? Qt : Qnil);
13006 if (!NILP (BVAR (current_buffer, bidi_display_reordering)))
13007 bset_bidi_paragraph_direction (current_buffer, Qleft_to_right);
13008
13009
13010 TEMP_SET_PT_BOTH (BEG, BEG_BYTE);
13011
13012
13013
13014
13015 insert_from_string (string, 0, 0, SCHARS (string), SBYTES (string), true);
13016
13017 return false;
13018 }
13019
13020
13021
13022
13023
13024 void
13025 clear_message (bool current_p, bool last_displayed_p)
13026 {
13027 Lisp_Object preserve = Qnil;
13028
13029 if (current_p)
13030 {
13031 if (FUNCTIONP (Vclear_message_function)
13032
13033 && !garbage_collection_inhibited)
13034 {
13035 specpdl_ref count = SPECPDL_INDEX ();
13036 specbind (Qinhibit_quit, Qt);
13037 preserve = safe_call (1, Vclear_message_function);
13038 unbind_to (count, Qnil);
13039 }
13040
13041 if (!EQ (preserve, Qdont_clear_message))
13042 {
13043 echo_area_buffer[0] = Qnil;
13044 message_cleared_p = true;
13045 }
13046 }
13047
13048 if (last_displayed_p)
13049 echo_area_buffer[1] = Qnil;
13050
13051 message_buf_print = false;
13052 }
13053
13054
13055
13056
13057
13058
13059
13060
13061
13062
13063 static void
13064 clear_garbaged_frames (void)
13065 {
13066 if (frame_garbaged)
13067 {
13068 Lisp_Object tail, frame;
13069 struct frame *sf = SELECTED_FRAME ();
13070
13071 FOR_EACH_FRAME (tail, frame)
13072 {
13073 struct frame *f = XFRAME (frame);
13074
13075 if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f))
13076 {
13077 if (f->resized_p
13078
13079
13080
13081
13082
13083 && !(f != sf && (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))))
13084 redraw_frame (f);
13085 else
13086 clear_current_matrices (f);
13087
13088 #ifdef HAVE_WINDOW_SYSTEM
13089 if (FRAME_WINDOW_P (f)
13090 && FRAME_RIF (f)->clear_under_internal_border)
13091 FRAME_RIF (f)->clear_under_internal_border (f);
13092 #endif
13093 fset_redisplay (f);
13094 f->garbaged = false;
13095 f->resized_p = false;
13096 }
13097 }
13098
13099 frame_garbaged = false;
13100 }
13101 }
13102
13103
13104
13105
13106
13107 static void
13108 echo_area_display (bool update_frame_p)
13109 {
13110 Lisp_Object mini_window;
13111 struct window *w;
13112 struct frame *f;
13113 bool window_height_changed_p = false;
13114 struct frame *sf = SELECTED_FRAME ();
13115
13116 mini_window = FRAME_MINIBUF_WINDOW (sf);
13117 if (NILP (mini_window))
13118 return;
13119
13120 w = XWINDOW (mini_window);
13121 f = XFRAME (WINDOW_FRAME (w));
13122
13123
13124 if (!FRAME_VISIBLE_P (f) || !f->glyphs_initialized_p)
13125 return;
13126
13127 #ifdef HAVE_WINDOW_SYSTEM
13128
13129
13130
13131 if (FRAME_INITIAL_P (XFRAME (selected_frame)))
13132 return;
13133 #endif
13134
13135
13136 clear_garbaged_frames ();
13137
13138 if (!NILP (echo_area_buffer[0]) || minibuf_level == 0)
13139 {
13140 echo_area_window = mini_window;
13141 window_height_changed_p = display_echo_area (w);
13142 w->must_be_updated_p = true;
13143
13144
13145
13146
13147
13148 if (update_frame_p && !redisplaying_p)
13149 {
13150 int n = 0;
13151
13152
13153
13154
13155
13156
13157 if (!display_completed)
13158 {
13159 n = redisplay_mode_lines (FRAME_ROOT_WINDOW (f), false);
13160
13161 #ifdef HAVE_WINDOW_SYSTEM
13162 if (FRAME_WINDOW_P (f)
13163 && FRAME_RIF (f)->clear_under_internal_border)
13164 FRAME_RIF (f)->clear_under_internal_border (f);
13165 #endif
13166 }
13167
13168 if (window_height_changed_p
13169
13170
13171 && !NILP (Vrun_hooks))
13172 {
13173
13174
13175
13176 specpdl_ref count = SPECPDL_INDEX ();
13177 specbind (Qredisplay_dont_pause, Qt);
13178 fset_redisplay (f);
13179 redisplay_internal ();
13180 unbind_to (count, Qnil);
13181 }
13182 else if (FRAME_WINDOW_P (f) && n == 0)
13183 {
13184
13185
13186
13187 update_single_window (w);
13188 flush_frame (f);
13189 }
13190 else
13191 update_frame (f, true, true);
13192
13193
13194
13195
13196 if (cursor_in_echo_area)
13197 wset_redisplay (XWINDOW (mini_window));
13198 }
13199 }
13200 else if (!EQ (mini_window, selected_window))
13201 wset_redisplay (XWINDOW (mini_window));
13202
13203
13204 echo_area_buffer[1] = echo_area_buffer[0];
13205
13206 echo_message_buffer = Qnil;
13207
13208
13209
13210
13211 if (EQ (mini_window, selected_window))
13212 CHARPOS (this_line_start_pos) = 0;
13213
13214 if (window_height_changed_p)
13215 {
13216 fset_redisplay (f);
13217
13218
13219
13220
13221
13222 clear_garbaged_frames ();
13223 }
13224 }
13225
13226
13227
13228 static bool
13229 window_buffer_changed (struct window *w)
13230 {
13231 struct buffer *b = XBUFFER (w->contents);
13232
13233 eassert (BUFFER_LIVE_P (b));
13234
13235 return (BUF_SAVE_MODIFF (b) < BUF_MODIFF (b)) != w->last_had_star;
13236 }
13237
13238
13239
13240 static bool
13241 mode_line_update_needed (struct window *w)
13242 {
13243 return (w->column_number_displayed != -1
13244 && !(PT == w->last_point && !window_outdated (w))
13245 && (w->column_number_displayed != current_column ()));
13246 }
13247
13248
13249
13250
13251 static bool
13252 window_frozen_p (struct window *w)
13253 {
13254 if (FRAME_WINDOWS_FROZEN (XFRAME (WINDOW_FRAME (w))))
13255 {
13256 Lisp_Object window;
13257
13258 XSETWINDOW (window, w);
13259 if (MINI_WINDOW_P (w))
13260 return false;
13261 else if (EQ (window, selected_window))
13262 return false;
13263 else if (MINI_WINDOW_P (XWINDOW (selected_window))
13264 && EQ (window, Vminibuf_scroll_window))
13265
13266 return false;
13267 else
13268 return true;
13269 }
13270 return false;
13271 }
13272
13273
13274
13275
13276
13277
13278
13279
13280
13281 static char *mode_line_noprop_buf;
13282
13283
13284
13285 static char *mode_line_noprop_buf_end;
13286 static char *mode_line_noprop_ptr;
13287
13288 #define MODE_LINE_NOPROP_LEN(start) \
13289 ((mode_line_noprop_ptr - mode_line_noprop_buf) - start)
13290
13291 static enum {
13292 MODE_LINE_DISPLAY = 0,
13293 MODE_LINE_TITLE,
13294 MODE_LINE_NOPROP,
13295 MODE_LINE_STRING
13296 } mode_line_target;
13297
13298
13299
13300 static Lisp_Object mode_line_proptrans_alist;
13301
13302
13303 static Lisp_Object mode_line_string_list;
13304
13305
13306 static Lisp_Object mode_line_string_face;
13307 static Lisp_Object mode_line_string_face_prop;
13308
13309
13310
13311
13312 static Lisp_Object Vmode_line_unwind_vector;
13313
13314 static Lisp_Object
13315 format_mode_line_unwind_data (struct frame *target_frame,
13316 struct buffer *obuf,
13317 Lisp_Object owin,
13318 bool save_proptrans)
13319 {
13320 Lisp_Object vector, tmp;
13321
13322
13323
13324 vector = Vmode_line_unwind_vector;
13325 Vmode_line_unwind_vector = Qnil;
13326
13327 if (NILP (vector))
13328 vector = make_nil_vector (12);
13329
13330 ASET (vector, 0, make_fixnum (mode_line_target));
13331 ASET (vector, 1, make_fixnum (MODE_LINE_NOPROP_LEN (0)));
13332 ASET (vector, 2, mode_line_string_list);
13333 ASET (vector, 3, save_proptrans ? mode_line_proptrans_alist : Qt);
13334 ASET (vector, 4, mode_line_string_face);
13335 ASET (vector, 5, mode_line_string_face_prop);
13336
13337 if (obuf)
13338 XSETBUFFER (tmp, obuf);
13339 else
13340 tmp = Qnil;
13341 ASET (vector, 6, tmp);
13342 ASET (vector, 7, owin);
13343 if (target_frame)
13344 {
13345 Lisp_Object buffer = XWINDOW (target_frame->selected_window)->contents;
13346 struct buffer *b = XBUFFER (buffer);
13347 struct buffer *cb = current_buffer;
13348
13349
13350
13351
13352 ASET (vector, 8, target_frame->selected_window);
13353 if (FRAME_TERMCAP_P (target_frame))
13354 ASET (vector, 9, FRAME_TTY (target_frame)->top_frame);
13355
13356
13357
13358
13359 ASET (vector, 10, buffer);
13360 current_buffer = b;
13361 ASET (vector, 11, build_marker (current_buffer, PT, PT_BYTE));
13362 current_buffer = cb;
13363 }
13364
13365 return vector;
13366 }
13367
13368 static void
13369 unwind_format_mode_line (Lisp_Object vector)
13370 {
13371 Lisp_Object old_window = AREF (vector, 7);
13372 Lisp_Object target_frame_window = AREF (vector, 8);
13373 Lisp_Object old_top_frame = AREF (vector, 9);
13374
13375 mode_line_target = XFIXNUM (AREF (vector, 0));
13376 mode_line_noprop_ptr = mode_line_noprop_buf + XFIXNUM (AREF (vector, 1));
13377 mode_line_string_list = AREF (vector, 2);
13378 if (! EQ (AREF (vector, 3), Qt))
13379 mode_line_proptrans_alist = AREF (vector, 3);
13380 mode_line_string_face = AREF (vector, 4);
13381 mode_line_string_face_prop = AREF (vector, 5);
13382
13383
13384 if (WINDOW_LIVE_P (old_window))
13385 {
13386
13387
13388
13389 if (WINDOW_LIVE_P (target_frame_window))
13390 {
13391 Lisp_Object frame
13392 = WINDOW_FRAME (XWINDOW (target_frame_window));
13393
13394 if (!EQ (frame, WINDOW_FRAME (XWINDOW (old_window))))
13395 Fselect_window (target_frame_window, Qt);
13396
13397 if (!NILP (old_top_frame) && !EQ (old_top_frame, frame)
13398
13399
13400 && FRAME_LIVE_P (XFRAME (old_top_frame)))
13401 Fselect_frame (old_top_frame, Qt);
13402 }
13403
13404 Fselect_window (old_window, Qt);
13405
13406
13407
13408
13409 if (WINDOW_LIVE_P (target_frame_window))
13410 {
13411 Lisp_Object buffer = AREF (vector, 10);
13412
13413 if (BUFFER_LIVE_P (XBUFFER (buffer)))
13414 {
13415 struct buffer *cb = current_buffer;
13416
13417 current_buffer = XBUFFER (buffer);
13418 set_point_from_marker (AREF (vector, 11));
13419 ASET (vector, 11, Qnil);
13420 current_buffer = cb;
13421 }
13422 }
13423 }
13424
13425 if (!NILP (AREF (vector, 6)))
13426 {
13427 set_buffer_internal_1 (XBUFFER (AREF (vector, 6)));
13428 ASET (vector, 6, Qnil);
13429 }
13430
13431 Vmode_line_unwind_vector = vector;
13432 }
13433
13434
13435
13436
13437
13438 static void
13439 store_mode_line_noprop_char (char c)
13440 {
13441
13442
13443 if (mode_line_noprop_ptr == mode_line_noprop_buf_end)
13444 {
13445 ptrdiff_t len = MODE_LINE_NOPROP_LEN (0);
13446 ptrdiff_t size = len;
13447 mode_line_noprop_buf =
13448 xpalloc (mode_line_noprop_buf, &size, 1, STRING_BYTES_BOUND, 1);
13449 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
13450 mode_line_noprop_ptr = mode_line_noprop_buf + len;
13451 }
13452
13453 *mode_line_noprop_ptr++ = c;
13454 }
13455
13456
13457
13458
13459
13460
13461
13462
13463
13464
13465 static int
13466 store_mode_line_noprop (const char *string, int field_width, int precision)
13467 {
13468 const unsigned char *str = (const unsigned char *) string;
13469 int n = 0;
13470 ptrdiff_t dummy, nbytes;
13471
13472
13473 nbytes = strlen (string);
13474 n += c_string_width (str, nbytes, precision, &dummy, &nbytes);
13475 while (nbytes--)
13476 store_mode_line_noprop_char (*str++);
13477
13478
13479 while (field_width > 0
13480 && n < field_width)
13481 {
13482 store_mode_line_noprop_char (' ');
13483 ++n;
13484 }
13485
13486 return n;
13487 }
13488
13489
13490
13491
13492
13493 #ifdef HAVE_WINDOW_SYSTEM
13494
13495
13496
13497
13498
13499 void
13500 gui_consider_frame_title (Lisp_Object frame)
13501 {
13502 struct frame *f = XFRAME (frame);
13503 Lisp_Object format_data;
13504
13505 if ((FRAME_WINDOW_P (f)
13506 || FRAME_MINIBUF_ONLY_P (f)
13507 || f->explicit_name)
13508 && !FRAME_TOOLTIP_P (f))
13509 {
13510
13511 Lisp_Object tail, other_frame, fmt;
13512 ptrdiff_t title_start;
13513 char *title;
13514 ptrdiff_t len;
13515 struct it it;
13516 specpdl_ref count = SPECPDL_INDEX ();
13517
13518 FOR_EACH_FRAME (tail, other_frame)
13519 {
13520 struct frame *tf = XFRAME (other_frame);
13521
13522 if (tf != f
13523 && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
13524 && !FRAME_MINIBUF_ONLY_P (tf)
13525 && !FRAME_PARENT_FRAME (tf)
13526 && !FRAME_TOOLTIP_P (tf)
13527 && (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
13528 break;
13529 }
13530
13531
13532 multiple_frames = CONSP (tail);
13533
13534
13535
13536
13537
13538
13539
13540
13541
13542
13543
13544
13545 specbind (Qinhibit_redisplay, Qt);
13546
13547
13548
13549
13550
13551
13552
13553
13554 format_data = format_mode_line_unwind_data (f, current_buffer,
13555 selected_window,
13556 false);
13557 record_unwind_protect (unwind_format_mode_line, format_data);
13558
13559 Fselect_window (f->selected_window, Qt);
13560 set_buffer_internal_1 (XBUFFER (XWINDOW (f->selected_window)->contents));
13561 fmt = (FRAME_ICONIFIED_P (f) && !EQ (Vicon_title_format, Qt)
13562 ? Vicon_title_format : Vframe_title_format);
13563
13564 mode_line_target = MODE_LINE_TITLE;
13565 title_start = MODE_LINE_NOPROP_LEN (0);
13566 init_iterator (&it, XWINDOW (f->selected_window), -1, -1,
13567 NULL, DEFAULT_FACE_ID);
13568 display_mode_element (&it, 0, -1, -1, fmt, Qnil, false);
13569 len = MODE_LINE_NOPROP_LEN (title_start);
13570 title = mode_line_noprop_buf + title_start;
13571
13572
13573 ptrdiff_t nchars = 0;
13574 len = str_as_multibyte ((unsigned char *) title,
13575 mode_line_noprop_buf_end - title,
13576 len, &nchars);
13577 unbind_to (count, Qnil);
13578
13579
13580
13581
13582
13583
13584 if ((! STRINGP (f->name)
13585 || SBYTES (f->name) != len
13586 || memcmp (title, SDATA (f->name), len) != 0)
13587 && FRAME_TERMINAL (f)->implicit_set_name_hook)
13588 {
13589 Lisp_Object title_string = make_multibyte_string (title, nchars, len);
13590 FRAME_TERMINAL (f)->implicit_set_name_hook (f, title_string, Qnil);
13591 }
13592 }
13593 }
13594
13595 #endif
13596
13597
13598
13599
13600
13601
13602
13603 #define REDISPLAY_SOME_P() \
13604 ((windows_or_buffers_changed == 0 \
13605 || windows_or_buffers_changed == REDISPLAY_SOME) \
13606 && (update_mode_lines == 0 \
13607 || update_mode_lines == REDISPLAY_SOME))
13608
13609 static bool
13610 needs_no_redisplay (struct window *w)
13611 {
13612 struct buffer *buffer = XBUFFER (w->contents);
13613 struct frame *f = XFRAME (w->frame);
13614 return (REDISPLAY_SOME_P ()
13615 && !w->redisplay
13616 && !w->update_mode_line
13617 && !f->face_change
13618 && !f->redisplay
13619 && !buffer->text->redisplay
13620 && window_point (w) == w->last_point);
13621 }
13622
13623
13624
13625
13626 static void
13627 prepare_menu_bars (void)
13628 {
13629 bool all_windows = windows_or_buffers_changed || update_mode_lines;
13630 bool some_windows = REDISPLAY_SOME_P ();
13631
13632 if (FUNCTIONP (Vpre_redisplay_function))
13633 {
13634 Lisp_Object windows = all_windows ? Qt : Qnil;
13635 if (all_windows && some_windows)
13636 {
13637 Lisp_Object ws = window_list ();
13638 for (windows = Qnil; CONSP (ws); ws = XCDR (ws))
13639 {
13640 Lisp_Object this = XCAR (ws);
13641 struct window *w = XWINDOW (this);
13642
13643
13644 if (!needs_no_redisplay (w))
13645 windows = Fcons (this, windows);
13646 }
13647 }
13648 safe__call1 (true, Vpre_redisplay_function, windows);
13649 }
13650
13651
13652
13653
13654 #ifdef HAVE_WINDOW_SYSTEM
13655 if (all_windows)
13656 {
13657 Lisp_Object tail, frame;
13658
13659 FOR_EACH_FRAME (tail, frame)
13660 {
13661 struct frame *f = XFRAME (frame);
13662 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13663 if (some_windows
13664 && !f->redisplay
13665 && !w->redisplay
13666 && !XBUFFER (w->contents)->text->redisplay)
13667 continue;
13668
13669 if (!FRAME_TOOLTIP_P (f)
13670 && (FRAME_ICONIFIED_P (f)
13671 || FRAME_VISIBLE_P (f) == 1
13672
13673
13674
13675
13676
13677
13678
13679
13680
13681 || (FRAME_VISIBLE_P (f) == 2 && FRAME_WINDOW_P (f))))
13682 gui_consider_frame_title (frame);
13683 }
13684 }
13685 #endif
13686
13687
13688
13689
13690 if (all_windows)
13691 {
13692 Lisp_Object tail, frame;
13693 specpdl_ref count = SPECPDL_INDEX ();
13694
13695
13696 bool menu_bar_hooks_run = false;
13697
13698 record_unwind_save_match_data ();
13699
13700 FOR_EACH_FRAME (tail, frame)
13701 {
13702 struct frame *f = XFRAME (frame);
13703 struct window *w = XWINDOW (FRAME_SELECTED_WINDOW (f));
13704
13705
13706 if (FRAME_TOOLTIP_P (f))
13707 continue;
13708
13709 if (some_windows
13710 && !f->redisplay
13711 && !w->redisplay
13712 && !XBUFFER (w->contents)->text->redisplay)
13713 continue;
13714
13715 if (!FRAME_PARENT_FRAME (f))
13716 menu_bar_hooks_run = update_menu_bar (f, false, menu_bar_hooks_run);
13717
13718 update_tab_bar (f, false);
13719 #ifdef HAVE_WINDOW_SYSTEM
13720 update_tool_bar (f, false);
13721 #endif
13722 }
13723
13724 unbind_to (count, Qnil);
13725 }
13726 else
13727 {
13728 struct frame *sf = SELECTED_FRAME ();
13729
13730 if (!FRAME_PARENT_FRAME (sf))
13731 update_menu_bar (sf, true, false);
13732
13733 update_tab_bar (sf, true);
13734 #ifdef HAVE_WINDOW_SYSTEM
13735 update_tool_bar (sf, true);
13736 #endif
13737 }
13738 }
13739
13740
13741
13742
13743
13744
13745
13746
13747
13748
13749
13750
13751
13752 static bool
13753 update_menu_bar (struct frame *f, bool save_match_data, bool hooks_run)
13754 {
13755 Lisp_Object window;
13756 struct window *w;
13757
13758
13759
13760
13761 if (inhibit_menubar_update)
13762 return hooks_run;
13763
13764 window = FRAME_SELECTED_WINDOW (f);
13765 w = XWINDOW (window);
13766
13767 if (FRAME_WINDOW_P (f)
13768 ?
13769 #ifdef HAVE_EXT_MENU_BAR
13770 FRAME_EXTERNAL_MENU_BAR (f)
13771 #else
13772 FRAME_MENU_BAR_LINES (f) > 0
13773 #endif
13774 : FRAME_MENU_BAR_LINES (f) > 0)
13775 {
13776
13777
13778
13779
13780
13781
13782
13783 if (windows_or_buffers_changed
13784
13785
13786 || update_mode_lines
13787 || window_buffer_changed (w))
13788 {
13789 struct buffer *prev = current_buffer;
13790 specpdl_ref count = SPECPDL_INDEX ();
13791
13792 specbind (Qinhibit_menubar_update, Qt);
13793
13794 set_buffer_internal_1 (XBUFFER (w->contents));
13795 if (save_match_data)
13796 record_unwind_save_match_data ();
13797 if (NILP (Voverriding_local_map_menu_flag))
13798 {
13799 specbind (Qoverriding_terminal_local_map, Qnil);
13800 specbind (Qoverriding_local_map, Qnil);
13801 }
13802
13803 if (!hooks_run)
13804 {
13805
13806 safe_run_hooks (Qactivate_menubar_hook);
13807
13808
13809
13810 safe_run_hooks (Qmenu_bar_update_hook);
13811
13812 hooks_run = true;
13813 }
13814
13815 XSETFRAME (Vmenu_updating_frame, f);
13816 fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
13817
13818
13819 #ifdef HAVE_EXT_MENU_BAR
13820 if (FRAME_WINDOW_P (f))
13821 {
13822 #if defined (HAVE_NS)
13823
13824
13825 if (f == SELECTED_FRAME ())
13826 #endif
13827 set_frame_menubar (f, false);
13828 }
13829 else
13830
13831
13832 w->update_mode_line = true;
13833 #else
13834
13835
13836 w->update_mode_line = true;
13837 #endif
13838
13839 unbind_to (count, Qnil);
13840 set_buffer_internal_1 (prev);
13841 }
13842 }
13843
13844 return hooks_run;
13845 }
13846
13847
13848
13849
13850
13851
13852
13853
13854
13855
13856
13857
13858 static void
13859 restore_selected_window (Lisp_Object window)
13860 {
13861 if (WINDOW_LIVE_P (window))
13862
13863
13864 {
13865 selected_window = window;
13866 selected_frame = XWINDOW (window)->frame;
13867 FRAME_SELECTED_WINDOW (XFRAME (selected_frame)) = window;
13868 }
13869 else if (FRAMEP (selected_frame) && FRAME_LIVE_P (XFRAME (selected_frame)))
13870
13871
13872 selected_window = FRAME_SELECTED_WINDOW (XFRAME (selected_frame));
13873 else
13874
13875
13876
13877 {
13878 Lisp_Object tail;
13879 Lisp_Object frame UNINIT;
13880
13881 FOR_EACH_FRAME (tail, frame)
13882 {
13883 struct frame *f = XFRAME (frame);
13884
13885 if (!FRAME_PARENT_FRAME (f) && !FRAME_TOOLTIP_P (f))
13886 {
13887 selected_frame = frame;
13888 selected_window = FRAME_SELECTED_WINDOW (f);
13889
13890 return;
13891 }
13892 }
13893
13894
13895 emacs_abort ();
13896 }
13897 }
13898
13899
13900 static void
13901 restore_frame_selected_window (Lisp_Object window)
13902 {
13903 if (WINDOW_LIVE_P (window))
13904
13905
13906
13907 {
13908 Lisp_Object frame = XWINDOW (window)->frame;
13909
13910 FRAME_SELECTED_WINDOW (XFRAME (frame)) = window;
13911 if (EQ (frame, selected_frame))
13912 selected_window = window;
13913 }
13914 }
13915
13916
13917
13918
13919
13920
13921 static void
13922 update_tab_bar (struct frame *f, bool save_match_data)
13923 {
13924 bool do_update = false;
13925
13926 #ifdef HAVE_WINDOW_SYSTEM
13927 if (FRAME_WINDOW_P (f) && WINDOWP (f->tab_bar_window)) {
13928 if (WINDOW_TOTAL_LINES (XWINDOW (f->tab_bar_window)) > 0)
13929 do_update = true;
13930 }
13931 else
13932 #endif
13933 if (FRAME_TAB_BAR_LINES (f) > 0)
13934 do_update = true;
13935
13936 if (do_update)
13937 {
13938 Lisp_Object window;
13939 struct window *w;
13940
13941 window = FRAME_SELECTED_WINDOW (f);
13942 w = XWINDOW (window);
13943
13944
13945
13946
13947
13948
13949
13950
13951 if (windows_or_buffers_changed
13952 || w->update_mode_line
13953 || update_mode_lines
13954 || window_buffer_changed (w))
13955 {
13956 struct buffer *prev = current_buffer;
13957 specpdl_ref count = SPECPDL_INDEX ();
13958 Lisp_Object new_tab_bar;
13959 int new_n_tab_bar;
13960
13961
13962
13963
13964 set_buffer_internal_1 (XBUFFER (w->contents));
13965
13966
13967 if (save_match_data)
13968 record_unwind_save_match_data ();
13969
13970
13971 if (NILP (Voverriding_local_map_menu_flag))
13972 {
13973 specbind (Qoverriding_terminal_local_map, Qnil);
13974 specbind (Qoverriding_local_map, Qnil);
13975 }
13976
13977
13978
13979
13980
13981 eassert (EQ (selected_window,
13982
13983
13984 XFRAME (selected_frame)->selected_window));
13985 #ifdef HAVE_WINDOW_SYSTEM
13986 Lisp_Object frame;
13987 record_unwind_protect (restore_selected_window, selected_window);
13988 XSETFRAME (frame, f);
13989 selected_frame = frame;
13990 selected_window = FRAME_SELECTED_WINDOW (f);
13991 #endif
13992
13993
13994 new_tab_bar
13995 = tab_bar_items (Fcopy_sequence (f->tab_bar_items),
13996 &new_n_tab_bar);
13997
13998
13999 if (new_n_tab_bar != f->n_tab_bar_items
14000 || NILP (Fequal (new_tab_bar, f->tab_bar_items)))
14001 {
14002
14003
14004
14005 block_input ();
14006 fset_tab_bar_items (f, new_tab_bar);
14007 f->n_tab_bar_items = new_n_tab_bar;
14008 w->update_mode_line = true;
14009 unblock_input ();
14010 }
14011
14012 unbind_to (count, Qnil);
14013 set_buffer_internal_1 (prev);
14014 }
14015 }
14016 }
14017
14018
14019
14020
14021
14022
14023
14024
14025
14026
14027
14028 static void
14029 display_tab_bar (struct window *w)
14030 {
14031 struct frame *f = XFRAME (WINDOW_FRAME (w));
14032 struct it it;
14033 Lisp_Object items;
14034 int i;
14035
14036
14037 #ifdef HAVE_NTGUI
14038 if (FRAME_W32_P (f))
14039 return;
14040 #endif
14041 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14042 if (FRAME_X_P (f))
14043 return;
14044 #endif
14045
14046 #ifdef HAVE_NS
14047 if (FRAME_NS_P (f))
14048 return;
14049 #endif
14050
14051 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
14052 eassert (!FRAME_WINDOW_P (f));
14053 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14054 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14055 TAB_BAR_FACE_ID);
14056 it.first_visible_x = 0;
14057 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14058 #elif defined (HAVE_X_WINDOWS)
14059 if (FRAME_WINDOW_P (f))
14060 {
14061
14062
14063 struct window *tab_w;
14064 tab_w = XWINDOW (f->tab_bar_window);
14065 init_iterator (&it, tab_w, -1, -1, tab_w->desired_matrix->rows,
14066 TAB_BAR_FACE_ID);
14067 it.first_visible_x = 0;
14068 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
14069 }
14070 else
14071 #endif
14072 {
14073
14074
14075 init_iterator (&it, w, -1, -1, f->desired_matrix->rows
14076 + (FRAME_MENU_BAR_LINES (f) > 0 ? 1 : 0),
14077 TAB_BAR_FACE_ID);
14078 it.first_visible_x = 0;
14079 it.last_visible_x = FRAME_COLS (f);
14080 }
14081
14082
14083
14084
14085 it.paragraph_embedding = L2R;
14086
14087
14088 for (i = 0; i < FRAME_TAB_BAR_LINES (f); ++i)
14089 {
14090 struct glyph_row *row = it.glyph_row + i;
14091 clear_glyph_row (row);
14092 row->enabled_p = true;
14093 row->full_width_p = true;
14094 row->reversed_p = false;
14095 }
14096
14097
14098 items = it.f->tab_bar_items;
14099 int j;
14100 for (i = 0, j = 0; i < it.f->n_tab_bar_items; ++i, j += TAB_BAR_ITEM_NSLOTS)
14101 {
14102 Lisp_Object string = AREF (items, j + TAB_BAR_ITEM_CAPTION);
14103
14104
14105 if (NILP (string))
14106 break;
14107
14108 if (it.current_x < it.last_visible_x)
14109 display_string (NULL, string, Qnil, 0, 0, &it,
14110 SCHARS (string), 0, 0, STRING_MULTIBYTE (string));
14111 }
14112
14113
14114 if (it.current_x < it.last_visible_x)
14115 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
14116
14117
14118 compute_line_metrics (&it);
14119 }
14120
14121 #ifdef HAVE_WINDOW_SYSTEM
14122
14123
14124
14125
14126
14127 static void
14128 build_desired_tab_bar_string (struct frame *f)
14129 {
14130 int i;
14131 Lisp_Object caption;
14132
14133 caption = Qnil;
14134
14135
14136 fset_desired_tab_bar_string (f, build_string (""));
14137
14138
14139
14140
14141 for (i = 0; i < f->n_tab_bar_items; ++i)
14142 {
14143 #define PROP(IDX) \
14144 AREF (f->tab_bar_items, i * TAB_BAR_ITEM_NSLOTS + (IDX))
14145
14146 caption = Fcopy_sequence (PROP (TAB_BAR_ITEM_CAPTION));
14147
14148
14149
14150
14151
14152 AUTO_LIST2 (props, Qmenu_item, make_fixnum (i * TAB_BAR_ITEM_NSLOTS));
14153
14154 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14155 props, caption);
14156
14157 f->desired_tab_bar_string =
14158 concat2 (f->desired_tab_bar_string, caption);
14159
14160 #undef PROP
14161 }
14162 }
14163
14164
14165
14166
14167
14168
14169
14170
14171
14172
14173
14174
14175
14176
14177 static void
14178 display_tab_bar_line (struct it *it, int height)
14179 {
14180 struct glyph_row *row = it->glyph_row;
14181 int max_x = it->last_visible_x;
14182 struct glyph *last;
14183
14184
14185 clear_glyph_row (row);
14186 row->enabled_p = true;
14187 row->y = it->current_y;
14188
14189
14190
14191 it->start_of_box_run_p = true;
14192
14193 bool enough = false;
14194 while (it->current_x < max_x)
14195 {
14196 int x, n_glyphs_before, i, nglyphs;
14197 struct it it_before;
14198
14199
14200 if (!get_next_display_element (it))
14201 {
14202
14203 if (height < 0 && !it->hpos)
14204 return;
14205 break;
14206 }
14207
14208
14209 n_glyphs_before = row->used[TEXT_AREA];
14210 it_before = *it;
14211
14212 PRODUCE_GLYPHS (it);
14213
14214 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
14215 i = 0;
14216 x = it_before.current_x;
14217 while (i < nglyphs)
14218 {
14219 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
14220
14221 if (x + glyph->pixel_width > max_x)
14222 {
14223
14224 row->used[TEXT_AREA] = n_glyphs_before;
14225 *it = it_before;
14226
14227
14228
14229 if (n_glyphs_before == 0
14230 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
14231 break;
14232 goto out;
14233 }
14234
14235 ++it->hpos;
14236 x += glyph->pixel_width;
14237 ++i;
14238 }
14239
14240 enough = ITERATOR_AT_END_OF_LINE_P (it);
14241 set_iterator_to_next (it, true);
14242
14243
14244 if (enough)
14245 break;
14246 }
14247
14248 out:;
14249
14250 row->displays_text_p = row->used[TEXT_AREA] != 0;
14251
14252
14253
14254
14255
14256
14257
14258 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14259 && !EQ (Vauto_resize_tab_bars, Qgrow_only))
14260 it->face_id = DEFAULT_FACE_ID;
14261
14262 extend_face_to_end_of_line (it);
14263 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
14264 last->right_box_line_p = true;
14265 if (last == row->glyphs[TEXT_AREA])
14266 last->left_box_line_p = true;
14267
14268
14269 if ((height -= it->max_ascent + it->max_descent) > 0)
14270 {
14271
14272 height %= FRAME_LINE_HEIGHT (it->f);
14273 it->max_ascent += height / 2;
14274 it->max_descent += (height + 1) / 2;
14275 }
14276
14277 compute_line_metrics (it);
14278
14279
14280 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
14281 {
14282 row->height = row->phys_height = it->last_visible_y - row->y;
14283 row->visible_height = row->height;
14284 row->ascent = row->phys_ascent = 0;
14285 row->extra_line_spacing = 0;
14286 }
14287
14288 row->full_width_p = true;
14289 row->continued_p = false;
14290 row->truncated_on_left_p = false;
14291 row->truncated_on_right_p = false;
14292
14293 it->current_x = it->hpos = 0;
14294 it->current_y += row->height;
14295 ++it->vpos;
14296 ++it->glyph_row;
14297 }
14298
14299
14300
14301
14302
14303 static int
14304 tab_bar_height (struct frame *f, int *n_rows, bool pixelwise)
14305 {
14306 struct window *w = XWINDOW (f->tab_bar_window);
14307 struct it it;
14308
14309
14310
14311 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
14312
14313
14314
14315 init_iterator (&it, w, -1, -1, temp_row, TAB_BAR_FACE_ID);
14316 temp_row->reversed_p = false;
14317 it.first_visible_x = 0;
14318 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14319 reseat_to_string (&it, NULL, f->desired_tab_bar_string,
14320 0, 0, 0, STRING_MULTIBYTE (f->desired_tab_bar_string));
14321 it.paragraph_embedding = L2R;
14322
14323 clear_glyph_row (temp_row);
14324 while (!ITERATOR_AT_END_P (&it))
14325 {
14326 it.glyph_row = temp_row;
14327 display_tab_bar_line (&it, -1);
14328 }
14329 clear_glyph_row (temp_row);
14330
14331
14332 if (n_rows)
14333 *n_rows = it.vpos > 0 ? it.vpos : -1;
14334
14335 if (pixelwise)
14336 return it.current_y;
14337 else
14338 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
14339 }
14340
14341 DEFUN ("tab-bar-height", Ftab_bar_height, Stab_bar_height,
14342 0, 2, 0,
14343 doc:
14344
14345 )
14346 (Lisp_Object frame, Lisp_Object pixelwise)
14347 {
14348 int height = 0;
14349
14350 struct frame *f = decode_any_frame (frame);
14351
14352 if (WINDOWP (f->tab_bar_window)
14353 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tab_bar_window)) > 0)
14354 {
14355 update_tab_bar (f, true);
14356 if (f->n_tab_bar_items)
14357 {
14358 build_desired_tab_bar_string (f);
14359 height = tab_bar_height (f, NULL, !NILP (pixelwise));
14360 }
14361 }
14362
14363 return make_fixnum (height);
14364 }
14365
14366
14367
14368
14369 static bool
14370 redisplay_tab_bar (struct frame *f)
14371 {
14372 struct window *w;
14373 struct it it;
14374 struct glyph_row *row;
14375
14376 f->tab_bar_redisplayed = true;
14377
14378
14379
14380
14381
14382 if (!WINDOWP (f->tab_bar_window)
14383 || (w = XWINDOW (f->tab_bar_window),
14384 WINDOW_TOTAL_LINES (w) == 0))
14385 {
14386
14387
14388
14389
14390
14391 f->tab_bar_resized = true;
14392
14393 return false;
14394 }
14395
14396
14397 build_desired_tab_bar_string (f);
14398
14399 int new_nrows;
14400 int new_height = tab_bar_height (f, &new_nrows, true);
14401
14402 if (f->n_tab_bar_rows == 0)
14403 {
14404 f->n_tab_bar_rows = new_nrows;
14405 if (new_height != WINDOW_PIXEL_HEIGHT (w))
14406 frame_default_tab_bar_height = new_height;
14407 }
14408
14409
14410
14411 if (new_nrows > f->n_tab_bar_rows
14412 || (EQ (Vauto_resize_tab_bars, Qgrow_only)
14413 && !f->minimize_tab_bar_window_p
14414 && new_height > WINDOW_PIXEL_HEIGHT (w))
14415 || (! EQ (Vauto_resize_tab_bars, Qgrow_only)
14416 && new_height < WINDOW_PIXEL_HEIGHT (w)))
14417 {
14418 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14419 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14420 if (new_nrows != f->n_tab_bar_rows)
14421 f->n_tab_bar_rows = new_nrows;
14422 clear_glyph_matrix (w->desired_matrix);
14423 f->fonts_changed = true;
14424 return true;
14425 }
14426
14427
14428 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TAB_BAR_FACE_ID);
14429 it.first_visible_x = 0;
14430 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
14431 row = it.glyph_row;
14432 row->reversed_p = false;
14433 reseat_to_string (&it, NULL, f->desired_tab_bar_string, 0, 0, 0,
14434 STRING_MULTIBYTE (f->desired_tab_bar_string));
14435
14436
14437
14438
14439
14440
14441
14442 it.paragraph_embedding = L2R;
14443
14444
14445
14446 if (f->n_tab_bar_rows > 0)
14447 {
14448 int border, rows, height, extra;
14449
14450 if (TYPE_RANGED_FIXNUMP (int, Vtab_bar_border))
14451 border = XFIXNUM (Vtab_bar_border);
14452 else if (EQ (Vtab_bar_border, Qinternal_border_width))
14453 border = FRAME_INTERNAL_BORDER_WIDTH (f);
14454 else if (EQ (Vtab_bar_border, Qborder_width))
14455 border = f->border_width;
14456 else
14457 border = 0;
14458 if (border < 0)
14459 border = 0;
14460
14461 rows = f->n_tab_bar_rows;
14462 height = max (1, (it.last_visible_y - border) / rows);
14463 extra = it.last_visible_y - border - height * rows;
14464
14465 while (it.current_y < it.last_visible_y)
14466 {
14467 int h = 0;
14468 if (extra > 0 && rows-- > 0)
14469 {
14470 h = (extra + rows - 1) / rows;
14471 extra -= h;
14472 }
14473 display_tab_bar_line (&it, height + h);
14474 }
14475 }
14476 else
14477 {
14478 while (it.current_y < it.last_visible_y)
14479 display_tab_bar_line (&it, 0);
14480 }
14481
14482
14483
14484 w->desired_matrix->no_scrolling_p = true;
14485 w->must_be_updated_p = true;
14486
14487 if (!NILP (Vauto_resize_tab_bars))
14488 {
14489 bool change_height_p = false;
14490
14491
14492
14493 if (IT_STRING_CHARPOS (it) < it.end_charpos)
14494 change_height_p = true;
14495
14496
14497
14498
14499
14500 row = it.glyph_row - 1;
14501
14502
14503
14504
14505 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
14506 && row->height >= FRAME_LINE_HEIGHT (f))
14507 change_height_p = true;
14508
14509
14510
14511 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
14512 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
14513 change_height_p = true;
14514
14515
14516
14517 if (change_height_p)
14518 {
14519 int nrows;
14520 int new_height = tab_bar_height (f, &nrows, true);
14521
14522 change_height_p = ((EQ (Vauto_resize_tab_bars, Qgrow_only)
14523 && !f->minimize_tab_bar_window_p)
14524 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
14525 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
14526 f->minimize_tab_bar_window_p = false;
14527
14528 if (change_height_p)
14529 {
14530 if (FRAME_TERMINAL (f)->change_tab_bar_height_hook)
14531 FRAME_TERMINAL (f)->change_tab_bar_height_hook (f, new_height);
14532 frame_default_tab_bar_height = new_height;
14533 clear_glyph_matrix (w->desired_matrix);
14534 f->n_tab_bar_rows = nrows;
14535 f->fonts_changed = true;
14536
14537 return true;
14538 }
14539 }
14540 }
14541
14542 f->minimize_tab_bar_window_p = false;
14543 return false;
14544 }
14545
14546
14547
14548
14549
14550
14551
14552 static bool
14553 tab_bar_item_info (struct frame *f, struct glyph *glyph,
14554 int *prop_idx, bool *close_p)
14555 {
14556 Lisp_Object prop;
14557 ptrdiff_t charpos;
14558
14559
14560
14561
14562 charpos = min (SCHARS (f->current_tab_bar_string), glyph->charpos);
14563 charpos = max (0, charpos);
14564
14565
14566
14567
14568 prop = Fget_text_property (make_fixnum (charpos),
14569 Qmenu_item, f->current_tab_bar_string);
14570 if (! FIXNUMP (prop))
14571 return false;
14572 *prop_idx = XFIXNUM (prop);
14573
14574 *close_p = !NILP (Fget_text_property (make_fixnum (charpos),
14575 Qclose_tab,
14576 f->current_tab_bar_string));
14577
14578 return true;
14579 }
14580
14581
14582
14583
14584
14585
14586
14587
14588
14589
14590
14591
14592 static int
14593 get_tab_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
14594 int *hpos, int *vpos, int *prop_idx, bool *close_p)
14595 {
14596 struct window *w = XWINDOW (f->tab_bar_window);
14597 int area;
14598
14599
14600 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
14601 if (*glyph == NULL)
14602 return -1;
14603
14604
14605
14606 if (!tab_bar_item_info (f, *glyph, prop_idx, close_p))
14607 return -1;
14608
14609 return *prop_idx == f->last_tab_bar_item ? 0 : 1;
14610 }
14611
14612
14613
14614
14615
14616
14617
14618
14619 Lisp_Object
14620 handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14621 int modifiers)
14622 {
14623 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14624 struct window *w = XWINDOW (f->tab_bar_window);
14625 int hpos, vpos, prop_idx;
14626 bool close_p;
14627 struct glyph *glyph;
14628 Lisp_Object enabled_p;
14629 int ts;
14630
14631 frame_to_window_pixel_xy (w, &x, &y);
14632 ts = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14633 if (ts == -1)
14634 return Fcons (Qtab_bar, Qnil);
14635
14636
14637 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14638 if (NILP (enabled_p))
14639 return Qnil;
14640
14641 if (down_p)
14642 {
14643
14644 if (!NILP (Vmouse_highlight))
14645 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
14646 f->last_tab_bar_item = prop_idx;
14647 }
14648 else
14649 {
14650
14651 if (!NILP (Vmouse_highlight))
14652 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
14653 f->last_tab_bar_item = -1;
14654 }
14655
14656 Lisp_Object caption =
14657 Fcopy_sequence (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION));
14658
14659 AUTO_LIST2 (props, Qmenu_item,
14660 list3 (AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_KEY),
14661 AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_BINDING),
14662 close_p ? Qt : Qnil));
14663
14664 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14665 props, caption);
14666
14667 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14668 }
14669
14670
14671
14672
14673
14674
14675 static void
14676 note_tab_bar_highlight (struct frame *f, int x, int y)
14677 {
14678 Lisp_Object window = f->tab_bar_window;
14679 struct window *w = XWINDOW (window);
14680 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
14681 int hpos, vpos;
14682 struct glyph *glyph;
14683 struct glyph_row *row;
14684 int i;
14685 Lisp_Object enabled_p;
14686 int prop_idx;
14687 bool close_p;
14688 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
14689 int rc;
14690
14691
14692
14693 if (x <= 0 || y <= 0)
14694 {
14695 clear_mouse_face (hlinfo);
14696 return;
14697 }
14698
14699 rc = get_tab_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx, &close_p);
14700 if (rc < 0)
14701 {
14702
14703 clear_mouse_face (hlinfo);
14704 return;
14705 }
14706 else if (rc == 0)
14707
14708 goto set_help_echo;
14709
14710 clear_mouse_face (hlinfo);
14711
14712 bool mouse_down_p = false;
14713
14714
14715
14716
14717
14718 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
14719 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
14720 && f == dpyinfo->last_mouse_frame);
14721
14722 if (mouse_down_p && f->last_tab_bar_item != prop_idx
14723 && f->last_tab_bar_item != -1)
14724 return;
14725 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
14726
14727
14728 enabled_p = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_ENABLED_P);
14729 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
14730 {
14731
14732
14733 row = MATRIX_ROW (w->current_matrix, vpos);
14734 for (i = x = 0; i < hpos; ++i)
14735 x += row->glyphs[TEXT_AREA][i].pixel_width;
14736
14737
14738 hlinfo->mouse_face_beg_col = hpos;
14739 hlinfo->mouse_face_beg_row = vpos;
14740 hlinfo->mouse_face_beg_x = x;
14741 hlinfo->mouse_face_past_end = false;
14742
14743 hlinfo->mouse_face_end_col = hpos + 1;
14744 hlinfo->mouse_face_end_row = vpos;
14745 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
14746 hlinfo->mouse_face_window = window;
14747 hlinfo->mouse_face_face_id = TAB_BAR_FACE_ID;
14748
14749
14750 show_mouse_face (hlinfo, draw);
14751 }
14752
14753 set_help_echo:
14754
14755
14756
14757 help_echo_object = help_echo_window = Qnil;
14758 help_echo_pos = -1;
14759 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_HELP);
14760 if (NILP (help_echo_string))
14761 help_echo_string = AREF (f->tab_bar_items, prop_idx + TAB_BAR_ITEM_CAPTION);
14762 }
14763
14764 #endif
14765
14766
14767 static Lisp_Object
14768 tty_get_tab_bar_item (struct frame *f, int x, int *prop_idx, bool *close_p)
14769 {
14770 ptrdiff_t clen = 0;
14771
14772 for (int i = 0; i < f->n_tab_bar_items; i++)
14773 {
14774 Lisp_Object caption = AREF (f->tab_bar_items, (i * TAB_BAR_ITEM_NSLOTS
14775 + TAB_BAR_ITEM_CAPTION));
14776 if (NILP (caption))
14777 return Qnil;
14778 clen += SCHARS (caption);
14779 if (x < clen)
14780 {
14781 *prop_idx = i;
14782 *close_p = !NILP (Fget_text_property (make_fixnum (SCHARS (caption)
14783 - (clen - x)),
14784 Qclose_tab,
14785 caption));
14786 return caption;
14787 }
14788 }
14789 return Qnil;
14790 }
14791
14792
14793
14794
14795
14796
14797 Lisp_Object
14798 tty_handle_tab_bar_click (struct frame *f, int x, int y, bool down_p,
14799 struct input_event *event)
14800 {
14801
14802 if (y < FRAME_MENU_BAR_LINES (f)
14803 || y >= FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f))
14804 return Qnil;
14805
14806
14807 int prop_idx;
14808 bool close_p;
14809 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &close_p);
14810
14811 if (NILP (caption))
14812 return Qnil;
14813
14814 if (NILP (AREF (f->tab_bar_items,
14815 prop_idx * TAB_BAR_ITEM_NSLOTS + TAB_BAR_ITEM_ENABLED_P)))
14816 return Qnil;
14817
14818 if (down_p)
14819 f->last_tab_bar_item = prop_idx;
14820 else
14821 f->last_tab_bar_item = -1;
14822
14823 caption = Fcopy_sequence (caption);
14824
14825 AUTO_LIST2 (props, Qmenu_item,
14826 list3 (AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14827 + TAB_BAR_ITEM_KEY),
14828 AREF (f->tab_bar_items, prop_idx * TAB_BAR_ITEM_NSLOTS
14829 + TAB_BAR_ITEM_BINDING),
14830 close_p ? Qt : Qnil));
14831
14832 Fadd_text_properties (make_fixnum (0), make_fixnum (SCHARS (caption)),
14833 props, caption);
14834
14835 return Fcons (Qtab_bar, Fcons (caption, make_fixnum (0)));
14836 }
14837
14838
14839
14840
14841
14842
14843
14844 #ifdef HAVE_WINDOW_SYSTEM
14845
14846
14847
14848
14849
14850
14851 static void
14852 update_tool_bar (struct frame *f, bool save_match_data)
14853 {
14854 #ifdef HAVE_EXT_TOOL_BAR
14855 bool do_update = FRAME_EXTERNAL_TOOL_BAR (f);
14856 #else
14857 bool do_update = (WINDOWP (f->tool_bar_window)
14858 && WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)) > 0);
14859 #endif
14860
14861 if (do_update)
14862 {
14863 Lisp_Object window;
14864 struct window *w;
14865
14866 window = FRAME_SELECTED_WINDOW (f);
14867 w = XWINDOW (window);
14868
14869
14870
14871
14872
14873
14874
14875
14876 if (windows_or_buffers_changed
14877 || w->update_mode_line
14878 || update_mode_lines
14879 || window_buffer_changed (w))
14880 {
14881 struct buffer *prev = current_buffer;
14882 specpdl_ref count = SPECPDL_INDEX ();
14883 Lisp_Object frame, new_tool_bar;
14884 int new_n_tool_bar;
14885
14886
14887
14888
14889 set_buffer_internal_1 (XBUFFER (w->contents));
14890
14891
14892 if (save_match_data)
14893 record_unwind_save_match_data ();
14894
14895
14896 if (NILP (Voverriding_local_map_menu_flag))
14897 {
14898 specbind (Qoverriding_terminal_local_map, Qnil);
14899 specbind (Qoverriding_local_map, Qnil);
14900 }
14901
14902
14903
14904
14905
14906 eassert (EQ (selected_window,
14907
14908
14909 XFRAME (selected_frame)->selected_window));
14910 record_unwind_protect (restore_selected_window, selected_window);
14911 XSETFRAME (frame, f);
14912 selected_frame = frame;
14913 selected_window = FRAME_SELECTED_WINDOW (f);
14914
14915
14916 new_tool_bar
14917 = tool_bar_items (Fcopy_sequence (f->tool_bar_items),
14918 &new_n_tool_bar);
14919
14920
14921 if (new_n_tool_bar != f->n_tool_bar_items
14922 || NILP (Fequal (new_tool_bar, f->tool_bar_items)))
14923 {
14924
14925
14926
14927 block_input ();
14928 fset_tool_bar_items (f, new_tool_bar);
14929 f->n_tool_bar_items = new_n_tool_bar;
14930 w->update_mode_line = true;
14931 unblock_input ();
14932 }
14933
14934 unbind_to (count, Qnil);
14935 set_buffer_internal_1 (prev);
14936 }
14937 }
14938 }
14939
14940 #ifndef HAVE_EXT_TOOL_BAR
14941
14942
14943
14944
14945
14946 static void
14947 build_desired_tool_bar_string (struct frame *f)
14948 {
14949 int i, size, size_needed;
14950 Lisp_Object image, plist;
14951
14952 image = plist = Qnil;
14953
14954
14955
14956
14957
14958 size = (STRINGP (f->desired_tool_bar_string)
14959 ? SCHARS (f->desired_tool_bar_string)
14960 : 0);
14961
14962
14963 size_needed = f->n_tool_bar_items;
14964
14965
14966 if (size < size_needed || NILP (f->desired_tool_bar_string))
14967 fset_desired_tool_bar_string
14968 (f, Fmake_string (make_fixnum (size_needed), make_fixnum (' '), Qnil));
14969 else
14970 {
14971 AUTO_LIST4 (props, Qdisplay, Qnil, Qmenu_item, Qnil);
14972 Fremove_text_properties (make_fixnum (0), make_fixnum (size),
14973 props, f->desired_tool_bar_string);
14974 }
14975
14976
14977
14978
14979 for (i = 0; i < f->n_tool_bar_items; ++i)
14980 {
14981 #define PROP(IDX) \
14982 AREF (f->tool_bar_items, i * TOOL_BAR_ITEM_NSLOTS + (IDX))
14983
14984 bool enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P));
14985 bool selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P));
14986 int hmargin, vmargin, relief, idx, end;
14987
14988
14989
14990 image = PROP (TOOL_BAR_ITEM_IMAGES);
14991 if (VECTORP (image))
14992 {
14993 if (enabled_p)
14994 idx = (selected_p
14995 ? TOOL_BAR_IMAGE_ENABLED_SELECTED
14996 : TOOL_BAR_IMAGE_ENABLED_DESELECTED);
14997 else
14998 idx = (selected_p
14999 ? TOOL_BAR_IMAGE_DISABLED_SELECTED
15000 : TOOL_BAR_IMAGE_DISABLED_DESELECTED);
15001
15002 eassert (ASIZE (image) >= idx);
15003 image = AREF (image, idx);
15004 }
15005 else
15006 idx = -1;
15007
15008
15009 if (!valid_image_p (image))
15010 continue;
15011
15012
15013 plist = Fcopy_sequence (XCDR (image));
15014
15015
15016 relief = (tool_bar_button_relief >= 0
15017 ? min (tool_bar_button_relief,
15018 min (INT_MAX, MOST_POSITIVE_FIXNUM))
15019 : DEFAULT_TOOL_BAR_BUTTON_RELIEF);
15020 hmargin = vmargin = relief;
15021
15022 if (RANGED_FIXNUMP (1, Vtool_bar_button_margin,
15023 INT_MAX - max (hmargin, vmargin)))
15024 {
15025 hmargin += XFIXNAT (Vtool_bar_button_margin);
15026 vmargin += XFIXNAT (Vtool_bar_button_margin);
15027 }
15028 else if (CONSP (Vtool_bar_button_margin))
15029 {
15030 if (RANGED_FIXNUMP (1, XCAR (Vtool_bar_button_margin),
15031 INT_MAX - hmargin))
15032 hmargin += XFIXNAT (XCAR (Vtool_bar_button_margin));
15033
15034 if (RANGED_FIXNUMP (1, XCDR (Vtool_bar_button_margin),
15035 INT_MAX - vmargin))
15036 vmargin += XFIXNAT (XCDR (Vtool_bar_button_margin));
15037 }
15038
15039 if (auto_raise_tool_bar_buttons_p)
15040 {
15041
15042
15043 if (selected_p)
15044 {
15045 plist = plist_put (plist, QCrelief, make_fixnum (-relief));
15046 hmargin -= relief;
15047 vmargin -= relief;
15048 }
15049 }
15050 else
15051 {
15052
15053
15054
15055 plist = plist_put (plist, QCrelief,
15056 (selected_p
15057 ? make_fixnum (-relief)
15058 : make_fixnum (relief)));
15059 hmargin -= relief;
15060 vmargin -= relief;
15061 }
15062
15063
15064 if (hmargin || vmargin)
15065 {
15066 if (hmargin == vmargin)
15067 plist = plist_put (plist, QCmargin, make_fixnum (hmargin));
15068 else
15069 plist = plist_put (plist, QCmargin,
15070 Fcons (make_fixnum (hmargin),
15071 make_fixnum (vmargin)));
15072 }
15073
15074
15075
15076
15077 if (!enabled_p && idx < 0)
15078 plist = plist_put (plist, QCconversion, Qdisabled);
15079
15080
15081
15082
15083
15084 image = Fcons (Qimage, plist);
15085 AUTO_LIST4 (props, Qdisplay, image, Qmenu_item,
15086 make_fixnum (i * TOOL_BAR_ITEM_NSLOTS));
15087
15088
15089
15090
15091 if (i + 1 == f->n_tool_bar_items)
15092 end = SCHARS (f->desired_tool_bar_string);
15093 else
15094 end = i + 1;
15095 Fadd_text_properties (make_fixnum (i), make_fixnum (end),
15096 props, f->desired_tool_bar_string);
15097 #undef PROP
15098 }
15099 }
15100
15101
15102
15103
15104
15105
15106
15107
15108
15109
15110
15111
15112
15113
15114 static void
15115 display_tool_bar_line (struct it *it, int height)
15116 {
15117 struct glyph_row *row = it->glyph_row;
15118 int max_x = it->last_visible_x;
15119 struct glyph *last;
15120
15121
15122 clear_glyph_row (row);
15123 row->enabled_p = true;
15124 row->y = it->current_y;
15125
15126
15127
15128 it->start_of_box_run_p = true;
15129
15130 while (it->current_x < max_x)
15131 {
15132 int x, n_glyphs_before, i, nglyphs;
15133 struct it it_before;
15134
15135
15136 if (!get_next_display_element (it))
15137 {
15138
15139 if (height < 0 && !it->hpos)
15140 return;
15141 break;
15142 }
15143
15144
15145 n_glyphs_before = row->used[TEXT_AREA];
15146 it_before = *it;
15147
15148 PRODUCE_GLYPHS (it);
15149
15150 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
15151 i = 0;
15152 x = it_before.current_x;
15153 while (i < nglyphs)
15154 {
15155 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
15156
15157 if (x + glyph->pixel_width > max_x)
15158 {
15159
15160 row->used[TEXT_AREA] = n_glyphs_before;
15161 *it = it_before;
15162
15163
15164
15165 if (n_glyphs_before == 0
15166 && (it->vpos > 0 || IT_STRING_CHARPOS (*it) < it->end_charpos-1))
15167 break;
15168 goto out;
15169 }
15170
15171 ++it->hpos;
15172 x += glyph->pixel_width;
15173 ++i;
15174 }
15175
15176
15177 if (ITERATOR_AT_END_OF_LINE_P (it))
15178 break;
15179
15180 set_iterator_to_next (it, true);
15181 }
15182
15183 out:;
15184
15185 row->displays_text_p = row->used[TEXT_AREA] != 0;
15186
15187
15188
15189
15190
15191
15192
15193 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15194 && !EQ (Vauto_resize_tool_bars, Qgrow_only))
15195 it->face_id = DEFAULT_FACE_ID;
15196
15197 extend_face_to_end_of_line (it);
15198 last = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
15199 last->right_box_line_p = true;
15200 if (last == row->glyphs[TEXT_AREA])
15201 last->left_box_line_p = true;
15202
15203
15204 if ((height -= it->max_ascent + it->max_descent) > 0)
15205 {
15206
15207 height %= FRAME_LINE_HEIGHT (it->f);
15208 it->max_ascent += height / 2;
15209 it->max_descent += (height + 1) / 2;
15210 }
15211
15212 compute_line_metrics (it);
15213
15214
15215 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row))
15216 {
15217 row->height = row->phys_height = it->last_visible_y - row->y;
15218 row->visible_height = row->height;
15219 row->ascent = row->phys_ascent = 0;
15220 row->extra_line_spacing = 0;
15221 }
15222
15223 row->full_width_p = true;
15224 row->continued_p = false;
15225 row->truncated_on_left_p = false;
15226 row->truncated_on_right_p = false;
15227
15228 it->current_x = it->hpos = 0;
15229 it->current_y += row->height;
15230 ++it->vpos;
15231 ++it->glyph_row;
15232 }
15233
15234
15235
15236
15237
15238 static int
15239 tool_bar_height (struct frame *f, int *n_rows, bool pixelwise)
15240 {
15241 struct window *w = XWINDOW (f->tool_bar_window);
15242 struct it it;
15243
15244
15245
15246 struct glyph_row *temp_row = MATRIX_MODE_LINE_ROW (w->desired_matrix);
15247
15248
15249
15250 init_iterator (&it, w, -1, -1, temp_row, TOOL_BAR_FACE_ID);
15251 temp_row->reversed_p = false;
15252 it.first_visible_x = 0;
15253 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15254 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15255 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15256 it.paragraph_embedding = L2R;
15257
15258 while (!ITERATOR_AT_END_P (&it))
15259 {
15260 clear_glyph_row (temp_row);
15261 it.glyph_row = temp_row;
15262 display_tool_bar_line (&it, -1);
15263 }
15264 clear_glyph_row (temp_row);
15265
15266
15267 if (n_rows)
15268 *n_rows = it.vpos > 0 ? it.vpos : -1;
15269
15270 if (pixelwise)
15271 return it.current_y;
15272 else
15273 return (it.current_y + FRAME_LINE_HEIGHT (f) - 1) / FRAME_LINE_HEIGHT (f);
15274 }
15275
15276 #endif
15277
15278 DEFUN ("tool-bar-height", Ftool_bar_height, Stool_bar_height,
15279 0, 2, 0,
15280 doc:
15281
15282 )
15283 (Lisp_Object frame, Lisp_Object pixelwise)
15284 {
15285 int height = 0;
15286
15287 #ifndef HAVE_EXT_TOOL_BAR
15288 struct frame *f = decode_any_frame (frame);
15289
15290 if (WINDOWP (f->tool_bar_window)
15291 && WINDOW_PIXEL_HEIGHT (XWINDOW (f->tool_bar_window)) > 0)
15292 {
15293 update_tool_bar (f, true);
15294 if (f->n_tool_bar_items)
15295 {
15296 build_desired_tool_bar_string (f);
15297 height = tool_bar_height (f, NULL, !NILP (pixelwise));
15298 }
15299 }
15300 #endif
15301
15302 return make_fixnum (height);
15303 }
15304
15305 #ifndef HAVE_EXT_TOOL_BAR
15306
15307
15308
15309 static bool
15310 redisplay_tool_bar (struct frame *f)
15311 {
15312 struct window *w;
15313 struct it it;
15314 struct glyph_row *row;
15315
15316 f->tool_bar_redisplayed = true;
15317
15318
15319
15320
15321
15322 if (!WINDOWP (f->tool_bar_window)
15323 || (w = XWINDOW (f->tool_bar_window),
15324 WINDOW_TOTAL_LINES (w) == 0))
15325 {
15326
15327
15328
15329
15330
15331 f->tool_bar_resized = true;
15332
15333 return false;
15334 }
15335
15336
15337 init_iterator (&it, w, -1, -1, w->desired_matrix->rows, TOOL_BAR_FACE_ID);
15338 it.first_visible_x = 0;
15339 it.last_visible_x = WINDOW_PIXEL_WIDTH (w);
15340 row = it.glyph_row;
15341 row->reversed_p = false;
15342
15343
15344 build_desired_tool_bar_string (f);
15345 reseat_to_string (&it, NULL, f->desired_tool_bar_string,
15346 0, 0, 0, STRING_MULTIBYTE (f->desired_tool_bar_string));
15347
15348
15349
15350
15351
15352
15353
15354 it.paragraph_embedding = L2R;
15355
15356 if (f->n_tool_bar_rows == 0)
15357 {
15358 int new_height = tool_bar_height (f, &f->n_tool_bar_rows, true);
15359
15360 if (new_height != WINDOW_PIXEL_HEIGHT (w))
15361 {
15362 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15363 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15364 frame_default_tool_bar_height = new_height;
15365
15366 clear_glyph_matrix (w->desired_matrix);
15367 f->fonts_changed = true;
15368 return true;
15369 }
15370 }
15371
15372
15373
15374 if (f->n_tool_bar_rows > 0)
15375 {
15376 int border, rows, height, extra;
15377
15378 if (TYPE_RANGED_FIXNUMP (int, Vtool_bar_border))
15379 border = XFIXNUM (Vtool_bar_border);
15380 else if (EQ (Vtool_bar_border, Qinternal_border_width))
15381 border = FRAME_INTERNAL_BORDER_WIDTH (f);
15382 else if (EQ (Vtool_bar_border, Qborder_width))
15383 border = f->border_width;
15384 else
15385 border = 0;
15386 if (border < 0)
15387 border = 0;
15388
15389 rows = f->n_tool_bar_rows;
15390 height = max (1, (it.last_visible_y - border) / rows);
15391 extra = it.last_visible_y - border - height * rows;
15392
15393 while (it.current_y < it.last_visible_y)
15394 {
15395 int h = 0;
15396 if (extra > 0 && rows-- > 0)
15397 {
15398 h = (extra + rows - 1) / rows;
15399 extra -= h;
15400 }
15401 display_tool_bar_line (&it, height + h);
15402 }
15403 }
15404 else
15405 {
15406 while (it.current_y < it.last_visible_y)
15407 display_tool_bar_line (&it, 0);
15408 }
15409
15410
15411
15412 w->desired_matrix->no_scrolling_p = true;
15413 w->must_be_updated_p = true;
15414
15415 if (!NILP (Vauto_resize_tool_bars))
15416 {
15417 bool change_height_p = false;
15418
15419
15420
15421 if (IT_STRING_CHARPOS (it) < it.end_charpos)
15422 change_height_p = true;
15423
15424
15425
15426
15427
15428 row = it.glyph_row - 1;
15429
15430
15431
15432
15433 if (!MATRIX_ROW_DISPLAYS_TEXT_P (row)
15434 && row->height >= FRAME_LINE_HEIGHT (f))
15435 change_height_p = true;
15436
15437
15438
15439 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
15440 && MATRIX_ROW_BOTTOM_Y (row) > it.last_visible_y)
15441 change_height_p = true;
15442
15443
15444
15445 if (change_height_p)
15446 {
15447 int nrows;
15448 int new_height = tool_bar_height (f, &nrows, true);
15449
15450 change_height_p = ((EQ (Vauto_resize_tool_bars, Qgrow_only)
15451 && !f->minimize_tool_bar_window_p)
15452 ? (new_height > WINDOW_PIXEL_HEIGHT (w))
15453 : (new_height != WINDOW_PIXEL_HEIGHT (w)));
15454 f->minimize_tool_bar_window_p = false;
15455
15456 if (change_height_p)
15457 {
15458 if (FRAME_TERMINAL (f)->change_tool_bar_height_hook)
15459 FRAME_TERMINAL (f)->change_tool_bar_height_hook (f, new_height);
15460 frame_default_tool_bar_height = new_height;
15461 clear_glyph_matrix (w->desired_matrix);
15462 f->n_tool_bar_rows = nrows;
15463 f->fonts_changed = true;
15464
15465 return true;
15466 }
15467 }
15468 }
15469
15470 f->minimize_tool_bar_window_p = false;
15471
15472 return false;
15473 }
15474
15475
15476
15477
15478
15479
15480 static bool
15481 tool_bar_item_info (struct frame *f, struct glyph *glyph, int *prop_idx)
15482 {
15483 Lisp_Object prop;
15484 ptrdiff_t charpos;
15485
15486
15487
15488
15489 charpos = min (SCHARS (f->current_tool_bar_string), glyph->charpos);
15490 charpos = max (0, charpos);
15491
15492
15493
15494
15495 prop = Fget_text_property (make_fixnum (charpos),
15496 Qmenu_item, f->current_tool_bar_string);
15497 if (! FIXNUMP (prop))
15498 return false;
15499 *prop_idx = XFIXNUM (prop);
15500 return true;
15501 }
15502
15503
15504
15505
15506
15507
15508
15509
15510
15511
15512
15513
15514 static int
15515 get_tool_bar_item (struct frame *f, int x, int y, struct glyph **glyph,
15516 int *hpos, int *vpos, int *prop_idx)
15517 {
15518 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15519 struct window *w = XWINDOW (f->tool_bar_window);
15520 int area;
15521
15522
15523 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area);
15524 if (*glyph == NULL)
15525 return -1;
15526
15527
15528
15529 if (!tool_bar_item_info (f, *glyph, prop_idx))
15530 return -1;
15531
15532
15533 if (EQ (f->tool_bar_window, hlinfo->mouse_face_window)
15534 && *vpos >= hlinfo->mouse_face_beg_row
15535 && *vpos <= hlinfo->mouse_face_end_row
15536 && (*vpos > hlinfo->mouse_face_beg_row
15537 || *hpos >= hlinfo->mouse_face_beg_col)
15538 && (*vpos < hlinfo->mouse_face_end_row
15539 || *hpos < hlinfo->mouse_face_end_col
15540 || hlinfo->mouse_face_past_end))
15541 return 0;
15542
15543 return 1;
15544 }
15545
15546
15547
15548
15549
15550
15551
15552
15553 void
15554 handle_tool_bar_click_with_device (struct frame *f, int x, int y, bool down_p,
15555 int modifiers, Lisp_Object device)
15556 {
15557 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15558 struct window *w = XWINDOW (f->tool_bar_window);
15559 int hpos, vpos, prop_idx;
15560 struct glyph *glyph;
15561 Lisp_Object enabled_p;
15562 int ts;
15563
15564
15565
15566
15567
15568
15569
15570
15571 frame_to_window_pixel_xy (w, &x, &y);
15572 ts = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15573 if (ts == -1
15574 || (ts != 0 && !NILP (Vmouse_highlight)))
15575 return;
15576
15577
15578
15579
15580 if (NILP (Vmouse_highlight) && !down_p)
15581 prop_idx = f->last_tool_bar_item;
15582
15583
15584 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15585 if (NILP (enabled_p))
15586 return;
15587
15588 if (down_p)
15589 {
15590
15591 if (!NILP (Vmouse_highlight))
15592 show_mouse_face (hlinfo, DRAW_IMAGE_SUNKEN);
15593 f->last_tool_bar_item = prop_idx;
15594 }
15595 else
15596 {
15597 Lisp_Object key, frame;
15598 struct input_event event;
15599 EVENT_INIT (event);
15600
15601
15602 if (!NILP (Vmouse_highlight))
15603 show_mouse_face (hlinfo, DRAW_IMAGE_RAISED);
15604
15605 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
15606
15607 XSETFRAME (frame, f);
15608 event.kind = TOOL_BAR_EVENT;
15609 event.frame_or_window = frame;
15610 event.arg = key;
15611 event.modifiers = modifiers;
15612 event.device = device;
15613 kbd_buffer_store_event (&event);
15614 f->last_tool_bar_item = -1;
15615 }
15616 }
15617
15618 void
15619 handle_tool_bar_click (struct frame *f, int x, int y, bool down_p,
15620 int modifiers)
15621 {
15622 handle_tool_bar_click_with_device (f, x, y, down_p, modifiers, Qt);
15623 }
15624
15625
15626
15627
15628
15629 static void
15630 note_tool_bar_highlight (struct frame *f, int x, int y)
15631 {
15632 Lisp_Object window = f->tool_bar_window;
15633 struct window *w = XWINDOW (window);
15634 Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
15635 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
15636 int hpos, vpos;
15637 struct glyph *glyph;
15638 struct glyph_row *row;
15639 int i;
15640 Lisp_Object enabled_p;
15641 int prop_idx;
15642 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
15643 bool mouse_down_p;
15644 int rc;
15645
15646
15647
15648 if (x <= 0 || y <= 0)
15649 {
15650 clear_mouse_face (hlinfo);
15651 return;
15652 }
15653
15654 rc = get_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
15655 if (rc < 0)
15656 {
15657
15658 clear_mouse_face (hlinfo);
15659 return;
15660 }
15661 else if (rc == 0)
15662
15663 goto set_help_echo;
15664
15665 clear_mouse_face (hlinfo);
15666
15667
15668 mouse_down_p = (gui_mouse_grabbed (dpyinfo)
15669 && f == dpyinfo->last_mouse_frame);
15670
15671 if (mouse_down_p && f->last_tool_bar_item != prop_idx)
15672 return;
15673
15674 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
15675
15676
15677 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
15678 if (!NILP (enabled_p) && !NILP (Vmouse_highlight))
15679 {
15680
15681
15682 row = MATRIX_ROW (w->current_matrix, vpos);
15683 for (i = x = 0; i < hpos; ++i)
15684 x += row->glyphs[TEXT_AREA][i].pixel_width;
15685
15686
15687 hlinfo->mouse_face_beg_col = hpos;
15688 hlinfo->mouse_face_beg_row = vpos;
15689 hlinfo->mouse_face_beg_x = x;
15690 hlinfo->mouse_face_past_end = false;
15691
15692 hlinfo->mouse_face_end_col = hpos + 1;
15693 hlinfo->mouse_face_end_row = vpos;
15694 hlinfo->mouse_face_end_x = x + glyph->pixel_width;
15695 hlinfo->mouse_face_window = window;
15696 hlinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
15697
15698
15699 show_mouse_face (hlinfo, draw);
15700 }
15701
15702 set_help_echo:
15703
15704
15705
15706 help_echo_object = help_echo_window = Qnil;
15707 help_echo_pos = -1;
15708 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
15709 if (NILP (help_echo_string))
15710 help_echo_string = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
15711 }
15712
15713 #endif
15714
15715 #endif
15716
15717
15718
15719
15720
15721
15722
15723
15724
15725
15726
15727
15728
15729 static bool
15730 hscroll_window_tree (Lisp_Object window)
15731 {
15732 bool hscrolled_p = false;
15733 bool hscroll_relative_p = FLOATP (Vhscroll_step);
15734 int hscroll_step_abs = 0;
15735 double hscroll_step_rel = 0;
15736
15737 if (hscroll_relative_p)
15738 {
15739 hscroll_step_rel = XFLOAT_DATA (Vhscroll_step);
15740 if (hscroll_step_rel < 0)
15741 {
15742 hscroll_relative_p = false;
15743 hscroll_step_abs = 0;
15744 }
15745 }
15746 else if (TYPE_RANGED_FIXNUMP (int, Vhscroll_step))
15747 {
15748 hscroll_step_abs = XFIXNUM (Vhscroll_step);
15749 if (hscroll_step_abs < 0)
15750 hscroll_step_abs = 0;
15751 }
15752 else
15753 hscroll_step_abs = 0;
15754
15755 while (WINDOWP (window))
15756 {
15757 struct window *w = XWINDOW (window);
15758
15759 if (WINDOWP (w->contents))
15760 hscrolled_p |= hscroll_window_tree (w->contents);
15761 else if (w->cursor.vpos >= 0
15762
15763
15764
15765
15766
15767
15768 && !(w == XWINDOW (echo_area_window)
15769 && !NILP (echo_area_buffer[0])))
15770 {
15771 int h_margin;
15772 int text_area_width;
15773 struct glyph_row *cursor_row;
15774 struct glyph_row *bottom_row;
15775
15776 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->desired_matrix, w);
15777 if (w->cursor.vpos < bottom_row - w->desired_matrix->rows)
15778 cursor_row = MATRIX_ROW (w->desired_matrix, w->cursor.vpos);
15779 else
15780 cursor_row = bottom_row - 1;
15781
15782 if (!cursor_row->enabled_p)
15783 {
15784 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
15785 if (w->cursor.vpos < bottom_row - w->current_matrix->rows)
15786 cursor_row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
15787 else
15788 cursor_row = bottom_row - 1;
15789 }
15790 bool row_r2l_p = cursor_row->reversed_p;
15791 bool hscl = hscrolling_current_line_p (w);
15792 int x_offset = 0;
15793
15794
15795 if (!NILP (Vdisplay_line_numbers))
15796 {
15797 struct glyph *g;
15798 if (!row_r2l_p)
15799 {
15800 for (g = cursor_row->glyphs[TEXT_AREA];
15801 g < cursor_row->glyphs[TEXT_AREA]
15802 + cursor_row->used[TEXT_AREA];
15803 g++)
15804 {
15805 if (!(NILP (g->object) && g->charpos < 0))
15806 break;
15807 x_offset += g->pixel_width;
15808 }
15809 }
15810 else
15811 {
15812 for (g = cursor_row->glyphs[TEXT_AREA]
15813 + cursor_row->used[TEXT_AREA];
15814 g > cursor_row->glyphs[TEXT_AREA];
15815 g--)
15816 {
15817 if (!(NILP ((g - 1)->object) && (g - 1)->charpos < 0))
15818 break;
15819 x_offset += (g - 1)->pixel_width;
15820 }
15821 }
15822 }
15823 if (cursor_row->truncated_on_left_p)
15824 {
15825
15826 struct frame *f = XFRAME (WINDOW_FRAME (w));
15827 x_offset -= (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
15828 }
15829
15830 text_area_width = window_box_width (w, TEXT_AREA);
15831
15832
15833 h_margin = (clip_to_bounds (0, hscroll_margin, 1000000)
15834 * WINDOW_FRAME_COLUMN_WIDTH (w));
15835
15836
15837
15838 if (w->suspend_auto_hscroll
15839 && NILP (Fequal (Fwindow_point (window),
15840 Fwindow_old_point (window))))
15841 {
15842 w->suspend_auto_hscroll = false;
15843
15844
15845
15846
15847 if (w->min_hscroll == 0 && w->hscroll > 0
15848 && EQ (Fbuffer_local_value (Qauto_hscroll_mode, w->contents),
15849 Qcurrent_line))
15850 SET_FRAME_GARBAGED (XFRAME (w->frame));
15851 }
15852
15853
15854 Fset_marker (w->old_pointm,
15855 ((w == XWINDOW (selected_window))
15856 ? make_fixnum (BUF_PT (XBUFFER (w->contents)))
15857 : Fmarker_position (w->pointm)),
15858 w->contents);
15859
15860 if (!NILP (Fbuffer_local_value (Qauto_hscroll_mode, w->contents))
15861 && !w->suspend_auto_hscroll
15862
15863
15864
15865
15866
15867
15868 && (CHARPOS (cursor_row->start.pos)
15869 >= BUF_BEG (XBUFFER (w->contents)))
15870
15871
15872
15873
15874 && ((!row_r2l_p
15875 && ((w->hscroll && w->cursor.x <= h_margin + x_offset)
15876 || (cursor_row->enabled_p
15877 && cursor_row->truncated_on_right_p
15878 && (w->cursor.x >= text_area_width - h_margin))))
15879
15880
15881
15882
15883
15884
15885 || (row_r2l_p
15886 && ((cursor_row->enabled_p
15887
15888
15889
15890 && cursor_row->truncated_on_right_p
15891 && w->cursor.x <= h_margin)
15892 || (w->hscroll
15893 && (w->cursor.x >= (text_area_width - h_margin
15894 - x_offset)))))
15895
15896
15897
15898
15899
15900 || (hscl
15901 && w->hscroll != w->min_hscroll
15902 && !cursor_row->truncated_on_left_p)))
15903 {
15904 struct it it;
15905 ptrdiff_t hscroll;
15906 struct buffer *saved_current_buffer;
15907 ptrdiff_t pt;
15908 int wanted_x;
15909
15910
15911 saved_current_buffer = current_buffer;
15912 current_buffer = XBUFFER (w->contents);
15913
15914 if (w == XWINDOW (selected_window))
15915 pt = PT;
15916 else
15917 pt = clip_to_bounds (BEGV, marker_position (w->pointm), ZV);
15918
15919
15920
15921 init_to_row_start (&it, w, cursor_row);
15922 if (hscl)
15923 it.first_visible_x = window_hscroll_limited (w, it.f)
15924 * FRAME_COLUMN_WIDTH (it.f);
15925 it.last_visible_x = DISP_INFINITY;
15926
15927 ptrdiff_t nchars = pt - IT_CHARPOS (it);
15928 if (current_buffer->long_line_optimizations_p
15929 && nchars > large_hscroll_threshold)
15930 {
15931
15932
15933
15934
15935 fast_move_it_horizontally (&it, nchars);
15936 it.current_x += nchars * FRAME_COLUMN_WIDTH (it.f);
15937 }
15938 else
15939 move_it_in_display_line_to (&it, pt, -1, MOVE_TO_POS);
15940
15941
15942
15943
15944
15945
15946 if (it.method == GET_FROM_STRING && pt > 1)
15947 {
15948 init_to_row_start (&it, w, cursor_row);
15949 if (hscl)
15950 it.first_visible_x = (window_hscroll_limited (w, it.f)
15951 * FRAME_COLUMN_WIDTH (it.f));
15952 if (current_buffer->long_line_optimizations_p
15953 && nchars > large_hscroll_threshold)
15954 {
15955 fast_move_it_horizontally (&it, nchars - 1);
15956 it.current_x += (nchars - 1) * FRAME_COLUMN_WIDTH (it.f);
15957 }
15958 else
15959 move_it_in_display_line_to (&it, pt - 1, -1, MOVE_TO_POS);
15960 }
15961 current_buffer = saved_current_buffer;
15962
15963
15964 if (!hscroll_relative_p && hscroll_step_abs == 0)
15965 hscroll = max (0, (it.current_x
15966 - (ITERATOR_AT_END_OF_LINE_P (&it)
15967 ? (text_area_width - 4 * FRAME_COLUMN_WIDTH (it.f))
15968 : (text_area_width / 2))))
15969 / FRAME_COLUMN_WIDTH (it.f);
15970 else if ((!row_r2l_p
15971 && w->cursor.x >= text_area_width - h_margin)
15972 || (row_r2l_p && w->cursor.x <= h_margin))
15973 {
15974 if (hscroll_relative_p)
15975 wanted_x = text_area_width * (1 - hscroll_step_rel)
15976 - h_margin;
15977 else
15978 wanted_x = text_area_width
15979 - hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
15980 - h_margin;
15981 hscroll
15982 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
15983 }
15984 else
15985 {
15986 if (hscroll_relative_p)
15987 wanted_x =
15988 text_area_width * hscroll_step_rel + h_margin + x_offset;
15989 else
15990 wanted_x =
15991 hscroll_step_abs * FRAME_COLUMN_WIDTH (it.f)
15992 + h_margin + x_offset;
15993 hscroll
15994 = max (0, it.current_x - wanted_x) / FRAME_COLUMN_WIDTH (it.f);
15995 }
15996 hscroll = max (hscroll, w->min_hscroll);
15997
15998
15999
16000
16001 if (w->hscroll != hscroll
16002
16003
16004
16005
16006 || (hscl && w->last_cursor_vpos != w->cursor.vpos))
16007 {
16008 struct buffer *b = XBUFFER (w->contents);
16009 b->prevent_redisplay_optimizations_p = true;
16010 w->hscroll = hscroll;
16011 hscrolled_p = true;
16012 }
16013 }
16014 }
16015
16016 window = w->next;
16017 }
16018
16019
16020 return hscrolled_p;
16021 }
16022
16023
16024
16025
16026
16027
16028
16029
16030 static bool
16031 hscroll_windows (Lisp_Object window)
16032 {
16033 bool hscrolled_p = hscroll_window_tree (window);
16034 if (hscrolled_p)
16035 clear_desired_matrices (XFRAME (WINDOW_FRAME (XWINDOW (window))));
16036 return hscrolled_p;
16037 }
16038
16039
16040
16041
16042
16043
16044
16045
16046
16047
16048 #ifdef GLYPH_DEBUG
16049
16050
16051
16052 static int debug_first_unchanged_at_end_vpos;
16053 static int debug_last_unchanged_at_beg_vpos;
16054
16055
16056
16057 static int debug_dvpos, debug_dy;
16058
16059
16060
16061 static ptrdiff_t debug_delta, debug_delta_bytes;
16062
16063
16064
16065
16066 static ptrdiff_t debug_end_vpos;
16067
16068
16069
16070
16071
16072 static void debug_method_add (struct window *, char const *, ...)
16073 ATTRIBUTE_FORMAT_PRINTF (2, 3);
16074
16075 static void
16076 debug_method_add (struct window *w, char const *fmt, ...)
16077 {
16078 void *ptr = w;
16079 char *method = w->desired_matrix->method;
16080 int len = strlen (method);
16081 int size = sizeof w->desired_matrix->method;
16082 int remaining = size - len - 1;
16083 va_list ap;
16084
16085 if (len && remaining)
16086 {
16087 method[len] = '|';
16088 --remaining, ++len;
16089 }
16090
16091 va_start (ap, fmt);
16092 vsnprintf (method + len, remaining + 1, fmt, ap);
16093 va_end (ap);
16094
16095 if (trace_redisplay_p)
16096 fprintf (stderr, "%p (%s): %s\n",
16097 ptr,
16098 ((BUFFERP (w->contents)
16099 && STRINGP (BVAR (XBUFFER (w->contents), name)))
16100 ? SSDATA (BVAR (XBUFFER (w->contents), name))
16101 : "no buffer"),
16102 method + len);
16103 }
16104
16105 #endif
16106
16107
16108
16109
16110
16111
16112
16113 static bool
16114 text_outside_line_unchanged_p (struct window *w,
16115 ptrdiff_t start, ptrdiff_t end)
16116 {
16117 bool unchanged_p = true;
16118
16119
16120 if (window_outdated (w))
16121 {
16122
16123 if (GPT < start || Z - GPT < end)
16124 unchanged_p = false;
16125
16126
16127 if (unchanged_p
16128 && (BEG_UNCHANGED < start - 1
16129 || END_UNCHANGED < end))
16130 unchanged_p = false;
16131
16132
16133
16134 if (unchanged_p
16135 && FIXNUMP (BVAR (current_buffer, selective_display))
16136 && XFIXNUM (BVAR (current_buffer, selective_display)) > 0
16137 && (BEG_UNCHANGED < start || GPT <= start))
16138 unchanged_p = false;
16139
16140
16141
16142
16143
16144
16145
16146
16147 if (unchanged_p)
16148 {
16149 if (BEG + BEG_UNCHANGED == start
16150 && overlay_touches_p (start))
16151 unchanged_p = false;
16152 if (END_UNCHANGED == end
16153 && overlay_touches_p (Z - end))
16154 unchanged_p = false;
16155 }
16156
16157
16158
16159
16160
16161
16162
16163
16164 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
16165 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
16166 unchanged_p = false;
16167 }
16168
16169 return unchanged_p;
16170 }
16171
16172
16173
16174
16175
16176
16177
16178
16179
16180 void
16181 redisplay (void)
16182 {
16183 redisplay_internal ();
16184 }
16185
16186
16187 static Lisp_Object
16188 overlay_arrow_string_or_property (Lisp_Object var)
16189 {
16190 Lisp_Object val;
16191
16192 if (val = Fget (var, Qoverlay_arrow_string), STRINGP (val))
16193 return val;
16194
16195 return Voverlay_arrow_string;
16196 }
16197
16198
16199 static bool
16200 overlay_arrow_in_current_buffer_p (void)
16201 {
16202 Lisp_Object vlist;
16203
16204 for (vlist = Voverlay_arrow_variable_list;
16205 CONSP (vlist);
16206 vlist = XCDR (vlist))
16207 {
16208 Lisp_Object var = XCAR (vlist);
16209 Lisp_Object val;
16210
16211 if (!SYMBOLP (var))
16212 continue;
16213 val = find_symbol_value (var);
16214 if (MARKERP (val)
16215 && current_buffer == XMARKER (val)->buffer)
16216 return true;
16217 }
16218 return false;
16219 }
16220
16221
16222
16223
16224
16225
16226
16227 static bool
16228 overlay_arrows_changed_p (bool set_redisplay)
16229 {
16230 Lisp_Object vlist;
16231 bool changed = false;
16232
16233 for (vlist = Voverlay_arrow_variable_list;
16234 CONSP (vlist);
16235 vlist = XCDR (vlist))
16236 {
16237 Lisp_Object var = XCAR (vlist);
16238 Lisp_Object val, pstr;
16239
16240 if (!SYMBOLP (var))
16241 continue;
16242 val = find_symbol_value (var);
16243 if (!MARKERP (val))
16244 continue;
16245 if (! EQ (Fmarker_position (val),
16246
16247
16248 Fget (var, Qlast_arrow_position))
16249 || ! (pstr = overlay_arrow_string_or_property (var),
16250 EQ (pstr, Fget (var, Qlast_arrow_string))))
16251 {
16252 struct buffer *buf = XMARKER (val)->buffer;
16253
16254 if (set_redisplay)
16255 {
16256 if (buf)
16257 bset_redisplay (buf);
16258 changed = true;
16259 }
16260 else
16261 return true;
16262 }
16263 }
16264 return changed;
16265 }
16266
16267
16268
16269 static void
16270 update_overlay_arrows (int up_to_date)
16271 {
16272 Lisp_Object vlist;
16273
16274 for (vlist = Voverlay_arrow_variable_list;
16275 CONSP (vlist);
16276 vlist = XCDR (vlist))
16277 {
16278 Lisp_Object var = XCAR (vlist);
16279
16280 if (!SYMBOLP (var))
16281 continue;
16282
16283 if (up_to_date > 0)
16284 {
16285 Lisp_Object val = find_symbol_value (var);
16286 if (!MARKERP (val))
16287 continue;
16288 Fput (var, Qlast_arrow_position, Fmarker_position (val));
16289 Fput (var, Qlast_arrow_string,
16290 overlay_arrow_string_or_property (var));
16291 }
16292 else if (up_to_date < 0
16293 || !NILP (Fget (var, Qlast_arrow_position)))
16294 {
16295 Fput (var, Qlast_arrow_position, Qt);
16296 Fput (var, Qlast_arrow_string, Qt);
16297 }
16298 }
16299 }
16300
16301
16302
16303
16304
16305
16306 static Lisp_Object
16307 overlay_arrow_at_row (struct it *it, struct glyph_row *row)
16308 {
16309 Lisp_Object vlist;
16310
16311 for (vlist = Voverlay_arrow_variable_list;
16312 CONSP (vlist);
16313 vlist = XCDR (vlist))
16314 {
16315 Lisp_Object var = XCAR (vlist);
16316 Lisp_Object val;
16317
16318 if (!SYMBOLP (var))
16319 continue;
16320
16321 val = find_symbol_value (var);
16322
16323 if (MARKERP (val)
16324 && current_buffer == XMARKER (val)->buffer
16325 && (MATRIX_ROW_START_CHARPOS (row) == marker_position (val)))
16326 {
16327 if (FRAME_WINDOW_P (it->f)
16328
16329
16330 && WINDOW_LEFT_FRINGE_WIDTH (it->w) > 0)
16331 {
16332 #ifdef HAVE_WINDOW_SYSTEM
16333 if (val = Fget (var, Qoverlay_arrow_bitmap), SYMBOLP (val))
16334 {
16335 int fringe_bitmap = lookup_fringe_bitmap (val);
16336 if (fringe_bitmap != 0)
16337 return make_fixnum (fringe_bitmap);
16338 }
16339 #endif
16340 return make_fixnum (-1);
16341 }
16342 return overlay_arrow_string_or_property (var);
16343 }
16344 }
16345
16346 return Qnil;
16347 }
16348
16349
16350
16351
16352
16353 static bool
16354 check_point_in_composition (struct buffer *prev_buf, ptrdiff_t prev_pt,
16355 struct buffer *buf, ptrdiff_t pt)
16356 {
16357 ptrdiff_t start, end;
16358 Lisp_Object prop;
16359 Lisp_Object buffer;
16360
16361 XSETBUFFER (buffer, buf);
16362
16363
16364 if (prev_buf == buf)
16365 {
16366 if (prev_pt == pt)
16367
16368 return false;
16369
16370 if (prev_pt > BUF_BEGV (buf) && prev_pt < BUF_ZV (buf)
16371 && find_composition (prev_pt, -1, &start, &end, &prop, buffer)
16372 && composition_valid_p (start, end, prop)
16373 && start < prev_pt && end > prev_pt)
16374
16375
16376 return (pt <= start || pt >= end);
16377 }
16378
16379
16380 return (pt > BUF_BEGV (buf) && pt < BUF_ZV (buf)
16381 && find_composition (pt, -1, &start, &end, &prop, buffer)
16382 && composition_valid_p (start, end, prop)
16383 && start < pt && end > pt);
16384 }
16385
16386
16387
16388 static void
16389 reconsider_clip_changes (struct window *w)
16390 {
16391 struct buffer *b = XBUFFER (w->contents);
16392
16393 if (b->clip_changed
16394 && w->window_end_valid
16395 && w->current_matrix->buffer == b
16396 && w->current_matrix->zv == BUF_ZV (b)
16397 && w->current_matrix->begv == BUF_BEGV (b))
16398 b->clip_changed = false;
16399
16400
16401
16402
16403
16404 if (!b->clip_changed && w->window_end_valid)
16405 {
16406 ptrdiff_t pt = (w == XWINDOW (selected_window)
16407 ? PT : marker_position (w->pointm));
16408
16409 if ((w->current_matrix->buffer != b || pt != w->last_point)
16410 && check_point_in_composition (w->current_matrix->buffer,
16411 w->last_point, b, pt))
16412 b->clip_changed = true;
16413 }
16414 }
16415
16416 static void
16417 propagate_buffer_redisplay (void)
16418 {
16419
16420
16421
16422
16423
16424
16425
16426
16427
16428 Lisp_Object ws = window_list ();
16429 for (; CONSP (ws); ws = XCDR (ws))
16430 {
16431 struct window *thisw = XWINDOW (XCAR (ws));
16432 struct buffer *thisb = XBUFFER (thisw->contents);
16433 if (thisb->text->redisplay)
16434 thisw->redisplay = true;
16435 }
16436 }
16437
16438 #define STOP_POLLING \
16439 do { if (! polling_stopped_here) stop_polling (); \
16440 polling_stopped_here = true; } while (false)
16441
16442 #define RESUME_POLLING \
16443 do { if (polling_stopped_here) start_polling (); \
16444 polling_stopped_here = false; } while (false)
16445
16446
16447
16448
16449 static void
16450 redisplay_internal (void)
16451 {
16452 struct window *w = XWINDOW (selected_window);
16453 struct window *sw;
16454 struct frame *fr;
16455 bool pending;
16456 bool must_finish = false, match_p;
16457 struct text_pos tlbufpos, tlendpos;
16458 int number_of_visible_frames;
16459 struct frame *sf;
16460 bool polling_stopped_here = false;
16461 Lisp_Object tail, frame;
16462
16463
16464
16465
16466 enum { MAX_HSCROLL_RETRIES = 16 };
16467 int hscroll_retries = 0;
16468
16469
16470
16471
16472
16473
16474 enum {MAX_GARBAGED_FRAME_RETRIES = 2 };
16475 int garbaged_frame_retries = 0;
16476
16477
16478
16479 bool consider_all_windows_p;
16480
16481
16482 bool update_miniwindow_p = false;
16483
16484 redisplay_trace ("redisplay_internal %d\n", redisplaying_p);
16485
16486
16487
16488
16489 if ((FRAME_INITIAL_P (SELECTED_FRAME ())
16490 && redisplay_skip_initial_frame)
16491 || !NILP (Vinhibit_redisplay))
16492 return;
16493
16494
16495
16496
16497 fr = XFRAME (w->frame);
16498 sf = SELECTED_FRAME ();
16499
16500 if (!fr->glyphs_initialized_p)
16501 return;
16502
16503 #if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS)
16504 if (popup_activated ())
16505 return;
16506 #endif
16507
16508 #if defined (HAVE_HAIKU)
16509 if (popup_activated_p)
16510 return;
16511 #endif
16512
16513
16514 if (redisplaying_p)
16515 return;
16516
16517
16518
16519 specpdl_ref count = SPECPDL_INDEX ();
16520 record_unwind_protect_void (unwind_redisplay);
16521 redisplaying_p = true;
16522 block_buffer_flips ();
16523 specbind (Qinhibit_free_realized_faces, Qnil);
16524
16525
16526 record_in_backtrace (Qredisplay_internal_xC_functionx, 0, 0);
16527
16528 FOR_EACH_FRAME (tail, frame)
16529 XFRAME (frame)->already_hscrolled_p = false;
16530
16531 reset_outermost_restrictions ();
16532
16533 retry:
16534
16535 sw = w;
16536
16537 pending = false;
16538 forget_escape_and_glyphless_faces ();
16539
16540 inhibit_free_realized_faces = false;
16541
16542
16543
16544
16545 if (face_change)
16546 windows_or_buffers_changed = 47;
16547
16548 if ((FRAME_TERMCAP_P (sf) || FRAME_MSDOS_P (sf))
16549 && FRAME_TTY (sf)->previous_frame != sf)
16550 {
16551
16552
16553
16554 SET_FRAME_GARBAGED (sf);
16555 #ifndef DOS_NT
16556 set_tty_color_mode (FRAME_TTY (sf), sf);
16557 #endif
16558 FRAME_TTY (sf)->previous_frame = sf;
16559 }
16560
16561
16562
16563
16564 number_of_visible_frames = 0;
16565
16566 FOR_EACH_FRAME (tail, frame)
16567 {
16568 struct frame *f = XFRAME (frame);
16569
16570 if (FRAME_VISIBLE_P (f))
16571 {
16572 ++number_of_visible_frames;
16573
16574 if (f->fonts_changed)
16575 {
16576 adjust_frame_glyphs (f);
16577
16578
16579
16580
16581
16582
16583 SET_FRAME_GARBAGED (f);
16584 f->fonts_changed = false;
16585 }
16586
16587
16588 if (f != sf && f->cursor_type_changed)
16589 fset_redisplay (f);
16590 }
16591 clear_desired_matrices (f);
16592 }
16593
16594
16595 do_pending_window_change (true);
16596
16597
16598 clear_garbaged_frames ();
16599
16600
16601 if (NILP (Vmemory_full))
16602 prepare_menu_bars ();
16603
16604
16605
16606
16607
16608 if (WINDOWP (selected_window) && (w = XWINDOW (selected_window)) != sw)
16609 sw = w;
16610
16611 reconsider_clip_changes (w);
16612
16613
16614 match_p = XBUFFER (w->contents) == current_buffer;
16615 if (match_p)
16616 {
16617
16618 if ((SAVE_MODIFF < MODIFF) != w->last_had_star)
16619 w->update_mode_line = true;
16620
16621 if (mode_line_update_needed (w))
16622 w->update_mode_line = true;
16623
16624
16625
16626
16627 if (current_buffer->clip_changed)
16628 bset_update_mode_line (current_buffer);
16629 }
16630
16631
16632
16633
16634
16635
16636 if ((!NILP (echo_area_buffer[0]) && !display_last_displayed_message_p)
16637 || (!NILP (echo_area_buffer[1]) && display_last_displayed_message_p)
16638 || (message_cleared_p
16639 && minibuf_level == 0
16640
16641
16642 && !MINI_WINDOW_P (XWINDOW (selected_window))))
16643 {
16644 echo_area_display (false);
16645
16646 if (message_cleared_p)
16647 update_miniwindow_p = true;
16648
16649 must_finish = true;
16650
16651
16652
16653
16654
16655 if (!display_last_displayed_message_p)
16656 message_cleared_p = false;
16657 }
16658 else if (EQ (selected_window, minibuf_window)
16659 && (current_buffer->clip_changed || window_outdated (w))
16660 && resize_mini_window (w, false))
16661 {
16662
16663
16664 must_finish = true;
16665
16666
16667
16668
16669 clear_garbaged_frames ();
16670 }
16671
16672 if (!NILP (Vrun_hooks))
16673 run_window_change_functions ();
16674
16675 if (windows_or_buffers_changed && !update_mode_lines)
16676
16677
16678
16679 update_mode_lines = (windows_or_buffers_changed == REDISPLAY_SOME
16680 ? REDISPLAY_SOME : 32);
16681
16682
16683
16684
16685
16686 overlay_arrows_changed_p (true);
16687
16688 consider_all_windows_p = (update_mode_lines
16689 || windows_or_buffers_changed);
16690
16691 #define AINC(a,i) \
16692 { \
16693 Lisp_Object entry = Fgethash (make_fixnum (i), a, make_fixnum (0)); \
16694 if (FIXNUMP (entry)) \
16695 Fputhash (make_fixnum (i), make_fixnum (1 + XFIXNUM (entry)), a); \
16696 }
16697
16698 AINC (Vredisplay__all_windows_cause, windows_or_buffers_changed);
16699 AINC (Vredisplay__mode_lines_cause, update_mode_lines);
16700
16701
16702
16703
16704
16705 tlbufpos = this_line_start_pos;
16706 tlendpos = this_line_end_pos;
16707 if (!consider_all_windows_p
16708 && CHARPOS (tlbufpos) > 0
16709 && !w->update_mode_line
16710 && !current_buffer->clip_changed
16711 && !current_buffer->prevent_redisplay_optimizations_p
16712 && FRAME_VISIBLE_P (XFRAME (w->frame))
16713 && !FRAME_OBSCURED_P (XFRAME (w->frame))
16714 && !XFRAME (w->frame)->cursor_type_changed
16715 && !XFRAME (w->frame)->face_change
16716
16717 && this_line_buffer == current_buffer
16718 && match_p
16719 && !w->force_start
16720 && !w->optional_new_start
16721
16722 && PT >= CHARPOS (tlbufpos)
16723 && PT <= Z - CHARPOS (tlendpos)
16724
16725
16726
16727
16728
16729
16730 && (NILP (Vdisplay_line_numbers)
16731 || EQ (Vdisplay_line_numbers, Qvisual))
16732
16733
16734 && text_outside_line_unchanged_p (w, CHARPOS (tlbufpos),
16735 CHARPOS (tlendpos)))
16736 {
16737 if (CHARPOS (tlbufpos) > BEGV
16738 && FETCH_BYTE (BYTEPOS (tlbufpos) - 1) != '\n'
16739 && (CHARPOS (tlbufpos) == ZV
16740 || FETCH_BYTE (BYTEPOS (tlbufpos)) == '\n'))
16741
16742 goto cancel;
16743 else if (window_outdated (w) || MINI_WINDOW_P (w))
16744 {
16745
16746
16747
16748
16749
16750
16751
16752
16753
16754
16755
16756
16757
16758
16759
16760 struct it it;
16761 int line_height_before = this_line_pixel_height;
16762
16763
16764
16765 start_display (&it, w, tlbufpos);
16766
16767
16768 if (it.current_x != this_line_start_x)
16769 goto cancel;
16770
16771
16772
16773
16774 if (it.sp > 1
16775 && it.method == GET_FROM_IMAGE && it.image_id == -1)
16776 goto cancel;
16777 redisplay_trace ("trying display optimization 1\n");
16778 w->cursor.vpos = -1;
16779 overlay_arrow_seen = false;
16780 it.vpos = this_line_vpos;
16781 it.current_y = this_line_y;
16782 it.glyph_row = MATRIX_ROW (w->desired_matrix, this_line_vpos);
16783 display_line (&it, -1);
16784
16785
16786
16787 if (w->cursor.vpos >= 0
16788
16789
16790 && CHARPOS (this_line_start_pos)
16791
16792 && CHARPOS (this_line_end_pos) == CHARPOS (tlendpos)
16793
16794
16795 && this_line_pixel_height == line_height_before
16796
16797
16798
16799
16800 && !hscrolling_current_line_p (w))
16801 {
16802
16803
16804 if (it.current_y < it.last_visible_y)
16805 {
16806 struct glyph_row *row
16807 = MATRIX_ROW (w->current_matrix, this_line_vpos + 1);
16808 ptrdiff_t delta, delta_bytes;
16809
16810
16811
16812
16813
16814
16815 delta = (Z
16816 - CHARPOS (tlendpos)
16817 - MATRIX_ROW_START_CHARPOS (row));
16818 delta_bytes = (Z_BYTE
16819 - BYTEPOS (tlendpos)
16820 - MATRIX_ROW_START_BYTEPOS (row));
16821
16822 increment_matrix_positions (w->current_matrix,
16823 this_line_vpos + 1,
16824 w->current_matrix->nrows,
16825 delta, delta_bytes);
16826 }
16827
16828
16829
16830
16831 if (MATRIX_ROW_DISPLAYS_TEXT_P (it.glyph_row - 1))
16832 {
16833 if (w->window_end_vpos < this_line_vpos)
16834 w->window_end_vpos = this_line_vpos;
16835 }
16836 else if (w->window_end_vpos == this_line_vpos
16837 && this_line_vpos > 0)
16838 w->window_end_vpos = this_line_vpos - 1;
16839 w->window_end_valid = false;
16840
16841
16842 w->desired_matrix->no_scrolling_p = true;
16843
16844 #ifdef GLYPH_DEBUG
16845 *w->desired_matrix->method = 0;
16846 debug_method_add (w, "optimization 1");
16847 #endif
16848 #ifdef HAVE_WINDOW_SYSTEM
16849 update_window_fringes (w, false);
16850 #endif
16851 goto update;
16852 }
16853 else
16854 goto cancel;
16855 }
16856 else if (
16857 PT == w->last_point
16858
16859
16860
16861
16862 && 0 <= w->cursor.vpos
16863 && w->cursor.vpos < WINDOW_TOTAL_LINES (w))
16864 {
16865 if (!must_finish)
16866 {
16867 do_pending_window_change (true);
16868
16869 if (WINDOWP (selected_window)
16870 && (w = XWINDOW (selected_window)) != sw)
16871 goto retry;
16872
16873
16874
16875 if (w->cursor_off_p == w->last_cursor_off_p)
16876 goto end_of_redisplay;
16877 }
16878 goto update;
16879 }
16880
16881
16882 else if (NILP (Vshow_trailing_whitespace)
16883 && !cursor_in_echo_area
16884 && !composition_break_at_point)
16885 {
16886 struct it it;
16887 struct glyph_row *row;
16888
16889
16890
16891
16892 init_iterator (&it, w, CHARPOS (tlbufpos), BYTEPOS (tlbufpos),
16893 NULL, DEFAULT_FACE_ID);
16894 it.current_x = this_line_start_x;
16895 it.current_y = this_line_y;
16896 it.vpos = this_line_vpos;
16897
16898 if (current_buffer->long_line_optimizations_p
16899 && it.line_wrap == TRUNCATE
16900 && PT - CHARPOS (tlbufpos) > large_hscroll_threshold)
16901 {
16902
16903
16904
16905 reseat_at_next_visible_line_start (&it, false);
16906 if (IT_CHARPOS (it) <= PT)
16907 it.vpos = this_line_vpos + 1;
16908 }
16909 else
16910 {
16911
16912
16913 move_it_to (&it, PT, -1, -1, -1, MOVE_TO_POS);
16914 }
16915
16916 if (it.vpos == this_line_vpos
16917 && (row = MATRIX_ROW (w->current_matrix, this_line_vpos),
16918 row->enabled_p))
16919 {
16920 eassert (this_line_vpos == it.vpos);
16921 eassert (this_line_y == it.current_y);
16922 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
16923 if (cursor_row_fully_visible_p (w, false, true, false))
16924 {
16925 #ifdef GLYPH_DEBUG
16926 *w->desired_matrix->method = 0;
16927 debug_method_add (w, "optimization 3");
16928 #endif
16929 goto update;
16930 }
16931 else
16932 goto cancel;
16933 }
16934 else
16935 goto cancel;
16936 }
16937
16938 cancel:
16939
16940 SET_MATRIX_ROW_ENABLED_P (w->desired_matrix, this_line_vpos, false);
16941 }
16942
16943 CHARPOS (this_line_start_pos) = 0;
16944 ++clear_face_cache_count;
16945 #ifdef HAVE_WINDOW_SYSTEM
16946 ++clear_image_cache_count;
16947 #endif
16948
16949
16950
16951
16952
16953
16954 if (consider_all_windows_p)
16955 {
16956 FOR_EACH_FRAME (tail, frame)
16957 XFRAME (frame)->updated_p = false;
16958
16959 propagate_buffer_redisplay ();
16960
16961 FOR_EACH_FRAME (tail, frame)
16962 {
16963 struct frame *f = XFRAME (frame);
16964
16965
16966
16967 if ((FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f))
16968 && !EQ (FRAME_TTY (f)->top_frame, frame))
16969 continue;
16970
16971 retry_frame:
16972 if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
16973 {
16974 bool gcscrollbars
16975
16976 = f->redisplay || !REDISPLAY_SOME_P ();
16977 bool f_redisplay_flag = f->redisplay;
16978
16979
16980
16981
16982 if (!FRAME_LIVE_P (f))
16983 continue;
16984
16985
16986
16987 if (gcscrollbars && FRAME_TERMINAL (f)->condemn_scroll_bars_hook)
16988 FRAME_TERMINAL (f)->condemn_scroll_bars_hook (f);
16989
16990 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
16991 {
16992
16993
16994
16995
16996
16997
16998
16999 f->inhibit_clear_image_cache = true;
17000 redisplay_windows (FRAME_ROOT_WINDOW (f));
17001 }
17002
17003
17004 else if (!REDISPLAY_SOME_P ())
17005 f->redisplay = true;
17006
17007
17008 if (!FRAME_LIVE_P (f))
17009 continue;
17010
17011
17012
17013 if (gcscrollbars && FRAME_TERMINAL (f)->judge_scroll_bars_hook)
17014 FRAME_TERMINAL (f)->judge_scroll_bars_hook (f);
17015
17016 if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
17017 {
17018
17019 if (f->fonts_changed)
17020 {
17021 adjust_frame_glyphs (f);
17022
17023
17024
17025 SET_FRAME_GARBAGED (f);
17026 f->fonts_changed = false;
17027 goto retry_frame;
17028 }
17029
17030
17031 if (!f->already_hscrolled_p)
17032 {
17033 f->already_hscrolled_p = true;
17034 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17035 && hscroll_windows (f->root_window))
17036 {
17037 hscroll_retries++;
17038 goto retry_frame;
17039 }
17040 }
17041
17042
17043
17044
17045
17046
17047
17048
17049
17050
17051
17052
17053 if (!f_redisplay_flag && f->redisplay)
17054 goto retry_frame;
17055
17056
17057
17058
17059
17060
17061
17062
17063
17064 if (FRAME_GARBAGED_P (f)
17065 && garbaged_frame_retries++ < MAX_GARBAGED_FRAME_RETRIES)
17066 goto retry;
17067
17068 #ifdef HAVE_WINDOW_SYSTEM
17069 if (FRAME_WINDOW_P (f)
17070 && FRAME_RIF (f)->clear_under_internal_border)
17071 FRAME_RIF (f)->clear_under_internal_border (f);
17072 #endif
17073
17074
17075
17076 if (interrupt_input)
17077 unrequest_sigio ();
17078 STOP_POLLING;
17079
17080 pending |= update_frame (f, false, false);
17081
17082
17083
17084
17085
17086
17087
17088 if (FRAME_GARBAGED_P (f))
17089 {
17090 fset_redisplay (f);
17091 f->garbaged = false;
17092 goto retry_frame;
17093 }
17094 f->cursor_type_changed = false;
17095 f->updated_p = true;
17096 f->inhibit_clear_image_cache = false;
17097 }
17098 }
17099 }
17100
17101 eassert (EQ (XFRAME (selected_frame)->selected_window, selected_window));
17102
17103 if (!pending)
17104 {
17105
17106
17107
17108 FOR_EACH_FRAME (tail, frame)
17109 {
17110 struct frame *f = XFRAME (frame);
17111 if (f->updated_p)
17112 {
17113 f->redisplay = false;
17114 f->garbaged = false;
17115 mark_window_display_accurate (f->root_window, true);
17116 if (FRAME_TERMINAL (f)->frame_up_to_date_hook)
17117 FRAME_TERMINAL (f)->frame_up_to_date_hook (f);
17118 }
17119 }
17120 }
17121 }
17122 else if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
17123 {
17124 sf->inhibit_clear_image_cache = true;
17125 displayed_buffer = XBUFFER (XWINDOW (selected_window)->contents);
17126
17127
17128 internal_condition_case_1 (redisplay_window_1, selected_window,
17129 list_of_error,
17130 redisplay_window_error);
17131 if (update_miniwindow_p)
17132 {
17133 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17134
17135 displayed_buffer = XBUFFER (XWINDOW (mini_window)->contents);
17136 internal_condition_case_1 (redisplay_window_1, mini_window,
17137 list_of_error,
17138 redisplay_window_error);
17139 }
17140
17141
17142
17143 update:
17144
17145
17146
17147 if (sf->fonts_changed || sf->redisplay)
17148 {
17149 if (sf->redisplay)
17150 {
17151
17152
17153
17154
17155
17156
17157 windows_or_buffers_changed = 50;
17158 }
17159 goto retry;
17160 }
17161
17162
17163
17164 inhibit_free_realized_faces = true;
17165
17166
17167
17168
17169 if (interrupt_input)
17170 unrequest_sigio ();
17171 STOP_POLLING;
17172
17173 if (FRAME_VISIBLE_P (sf) && !FRAME_OBSCURED_P (sf))
17174 {
17175 if (hscroll_retries <= MAX_HSCROLL_RETRIES
17176 && hscroll_windows (selected_window))
17177 {
17178 hscroll_retries++;
17179 goto retry;
17180 }
17181
17182 XWINDOW (selected_window)->must_be_updated_p = true;
17183 pending = update_frame (sf, false, false);
17184 sf->cursor_type_changed = false;
17185 sf->inhibit_clear_image_cache = false;
17186 }
17187
17188
17189
17190
17191
17192
17193 Lisp_Object mini_window = FRAME_MINIBUF_WINDOW (sf);
17194 struct frame *mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
17195
17196 if (mini_frame != sf && FRAME_WINDOW_P (mini_frame))
17197 {
17198 XWINDOW (mini_window)->must_be_updated_p = true;
17199 pending |= update_frame (mini_frame, false, false);
17200 mini_frame->cursor_type_changed = false;
17201 if (!pending && hscroll_retries <= MAX_HSCROLL_RETRIES
17202 && hscroll_windows (mini_window))
17203 {
17204 hscroll_retries++;
17205 goto retry;
17206 }
17207 }
17208 }
17209
17210
17211
17212 if (pending)
17213 {
17214
17215
17216
17217 CHARPOS (this_line_start_pos) = 0;
17218
17219
17220 update_overlay_arrows (0);
17221
17222
17223
17224 if (!WINDOW_FULL_WIDTH_P (w)
17225 && !FRAME_WINDOW_P (XFRAME (w->frame)))
17226 update_mode_lines = 36;
17227 }
17228 else
17229 {
17230 if (!consider_all_windows_p)
17231 {
17232
17233
17234 if (XBUFFER (w->contents)->text->redisplay
17235 && buffer_window_count (XBUFFER (w->contents)) > 1)
17236
17237
17238 propagate_buffer_redisplay ();
17239 mark_window_display_accurate_1 (w, true);
17240
17241
17242 update_overlay_arrows (1);
17243
17244 if (FRAME_TERMINAL (sf)->frame_up_to_date_hook != 0)
17245 FRAME_TERMINAL (sf)->frame_up_to_date_hook (sf);
17246 }
17247
17248 update_mode_lines = 0;
17249 windows_or_buffers_changed = 0;
17250 }
17251
17252
17253
17254
17255
17256 if (interrupt_input)
17257 request_sigio ();
17258 RESUME_POLLING;
17259
17260
17261
17262
17263
17264
17265
17266 if (!pending)
17267 {
17268 int new_count = 0;
17269
17270 FOR_EACH_FRAME (tail, frame)
17271 {
17272 if (XFRAME (frame)->visible)
17273 new_count++;
17274 }
17275
17276 if (new_count != number_of_visible_frames)
17277 windows_or_buffers_changed = 52;
17278 }
17279
17280
17281 do_pending_window_change (true);
17282
17283
17284
17285 if ((windows_or_buffers_changed && !pending)
17286 || (WINDOWP (selected_window)
17287 && (w = XWINDOW (selected_window)) != sw))
17288 goto retry;
17289
17290
17291
17292
17293
17294
17295
17296 if (clear_face_cache_count > CLEAR_FACE_CACHE_COUNT)
17297 {
17298 clear_face_cache (false);
17299 clear_face_cache_count = 0;
17300 }
17301
17302 #ifdef HAVE_WINDOW_SYSTEM
17303 if (clear_image_cache_count > CLEAR_IMAGE_CACHE_COUNT)
17304 {
17305 clear_image_caches (Qnil);
17306 clear_image_cache_count = 0;
17307 }
17308 #endif
17309
17310 end_of_redisplay:
17311 #ifdef HAVE_NS
17312 ns_set_doc_edited ();
17313 #endif
17314 if (interrupt_input && interrupts_deferred)
17315 request_sigio ();
17316
17317
17318
17319 if (max_redisplay_ticks > 0)
17320 update_redisplay_ticks (0, NULL);
17321
17322 unbind_to (count, Qnil);
17323 RESUME_POLLING;
17324 }
17325
17326 static void
17327 unwind_redisplay_preserve_echo_area (void)
17328 {
17329 unblock_buffer_flips ();
17330 }
17331
17332
17333
17334
17335
17336
17337
17338
17339
17340
17341
17342
17343 void
17344 redisplay_preserve_echo_area (int from_where)
17345 {
17346 redisplay_trace ("redisplay_preserve_echo_area (%d)\n", from_where);
17347
17348 block_input ();
17349 specpdl_ref count = SPECPDL_INDEX ();
17350 record_unwind_protect_void (unwind_redisplay_preserve_echo_area);
17351 block_buffer_flips ();
17352 unblock_input ();
17353
17354 if (!NILP (echo_area_buffer[1]))
17355 {
17356
17357
17358 display_last_displayed_message_p = true;
17359 redisplay_internal ();
17360 display_last_displayed_message_p = false;
17361 }
17362 else
17363 redisplay_internal ();
17364
17365 flush_frame (SELECTED_FRAME ());
17366 unbind_to (count, Qnil);
17367 }
17368
17369
17370
17371
17372 static void
17373 unwind_redisplay (void)
17374 {
17375 redisplaying_p = false;
17376 unblock_buffer_flips ();
17377 }
17378
17379
17380
17381 void
17382 unwind_display_working_on_window (void)
17383 {
17384 display_working_on_window_p = false;
17385 }
17386
17387
17388
17389
17390
17391
17392 static void
17393 mark_window_display_accurate_1 (struct window *w, bool accurate_p)
17394 {
17395 struct buffer *b = XBUFFER (w->contents);
17396
17397 w->last_modified = accurate_p ? BUF_MODIFF (b) : 0;
17398 w->last_overlay_modified = accurate_p ? BUF_OVERLAY_MODIFF (b) : 0;
17399 w->last_had_star = BUF_MODIFF (b) > BUF_SAVE_MODIFF (b);
17400
17401 if (accurate_p)
17402 {
17403 b->clip_changed = false;
17404 b->prevent_redisplay_optimizations_p = false;
17405 eassert (buffer_window_count (b) > 0);
17406
17407
17408
17409 b->text->redisplay = false;
17410
17411 BUF_UNCHANGED_MODIFIED (b) = BUF_MODIFF (b);
17412 BUF_OVERLAY_UNCHANGED_MODIFIED (b) = BUF_OVERLAY_MODIFF (b);
17413 BUF_BEG_UNCHANGED (b) = BUF_GPT (b) - BUF_BEG (b);
17414 BUF_END_UNCHANGED (b) = BUF_Z (b) - BUF_GPT (b);
17415
17416 w->current_matrix->buffer = b;
17417 w->current_matrix->begv = BUF_BEGV (b);
17418 w->current_matrix->zv = BUF_ZV (b);
17419 w->current_matrix->header_line_p = window_wants_header_line (w);
17420 w->current_matrix->tab_line_p = window_wants_tab_line (w);
17421
17422 w->last_cursor_vpos = w->cursor.vpos;
17423 w->last_cursor_off_p = w->cursor_off_p;
17424
17425 if (w == XWINDOW (selected_window))
17426 w->last_point = BUF_PT (b);
17427 else
17428 w->last_point = marker_position (w->pointm);
17429
17430 w->window_end_valid = true;
17431 w->update_mode_line = false;
17432 w->preserve_vscroll_p = false;
17433 }
17434
17435 w->redisplay = !accurate_p;
17436 }
17437
17438
17439
17440
17441
17442
17443
17444 void
17445 mark_window_display_accurate (Lisp_Object window, bool accurate_p)
17446 {
17447 struct window *w;
17448
17449 for (; !NILP (window); window = w->next)
17450 {
17451 w = XWINDOW (window);
17452 if (WINDOWP (w->contents))
17453 mark_window_display_accurate (w->contents, accurate_p);
17454 else
17455 mark_window_display_accurate_1 (w, accurate_p);
17456 }
17457
17458 if (accurate_p)
17459 update_overlay_arrows (1);
17460 else
17461
17462
17463
17464 update_overlay_arrows (-1);
17465 }
17466
17467
17468
17469
17470
17471
17472
17473 Lisp_Object
17474 disp_char_vector (struct Lisp_Char_Table *dp, int c)
17475 {
17476 Lisp_Object val;
17477
17478 if (ASCII_CHAR_P (c))
17479 {
17480 val = dp->ascii;
17481 if (SUB_CHAR_TABLE_P (val))
17482 val = XSUB_CHAR_TABLE (val)->contents[c];
17483 }
17484 else
17485 {
17486 Lisp_Object table;
17487
17488 XSETCHAR_TABLE (table, dp);
17489 val = char_table_ref (table, c);
17490 }
17491 if (NILP (val))
17492 val = dp->defalt;
17493 return val;
17494 }
17495
17496 static int buffer_flip_blocked_depth;
17497
17498 static void
17499 block_buffer_flips (void)
17500 {
17501 eassert (buffer_flip_blocked_depth >= 0);
17502 buffer_flip_blocked_depth++;
17503 }
17504
17505 static void
17506 unblock_buffer_flips (void)
17507 {
17508 eassert (buffer_flip_blocked_depth > 0);
17509 if (--buffer_flip_blocked_depth == 0)
17510 {
17511 Lisp_Object tail, frame;
17512 block_input ();
17513 FOR_EACH_FRAME (tail, frame)
17514 {
17515 struct frame *f = XFRAME (frame);
17516 if (FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook)
17517 (*FRAME_TERMINAL (f)->buffer_flipping_unblocked_hook) (f);
17518 }
17519 unblock_input ();
17520 }
17521 }
17522
17523 bool
17524 buffer_flipping_blocked_p (void)
17525 {
17526 return buffer_flip_blocked_depth > 0;
17527 }
17528
17529
17530
17531
17532
17533
17534
17535
17536 static void
17537 redisplay_windows (Lisp_Object window)
17538 {
17539 while (!NILP (window))
17540 {
17541 struct window *w = XWINDOW (window);
17542
17543 if (WINDOWP (w->contents))
17544 redisplay_windows (w->contents);
17545 else if (BUFFERP (w->contents))
17546 {
17547 displayed_buffer = XBUFFER (w->contents);
17548
17549
17550 internal_condition_case_1 (redisplay_window_0, window,
17551 list_of_error,
17552 redisplay_window_error);
17553 }
17554
17555 window = w->next;
17556 }
17557 }
17558
17559 static Lisp_Object
17560 redisplay_window_error (Lisp_Object error_data)
17561 {
17562 displayed_buffer->display_error_modiff = BUF_MODIFF (displayed_buffer);
17563
17564
17565
17566 if (max_redisplay_ticks > 0
17567 && CONSP (error_data)
17568 && EQ (XCAR (error_data), Qerror)
17569 && STRINGP (XCAR (XCDR (error_data))))
17570 Vdelayed_warnings_list = Fcons (list2 (XCAR (error_data),
17571 XCAR (XCDR (error_data))),
17572 Vdelayed_warnings_list);
17573 return Qnil;
17574 }
17575
17576 static Lisp_Object
17577 redisplay_window_0 (Lisp_Object window)
17578 {
17579 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17580 redisplay_window (window, false);
17581 return Qnil;
17582 }
17583
17584 static Lisp_Object
17585 redisplay_window_1 (Lisp_Object window)
17586 {
17587 if (displayed_buffer->display_error_modiff < BUF_MODIFF (displayed_buffer))
17588 redisplay_window (window, true);
17589 return Qnil;
17590 }
17591
17592
17593
17594
17595
17596
17597
17598
17599
17600
17601
17602
17603
17604
17605
17606
17607
17608
17609
17610 void
17611 update_redisplay_ticks (int ticks, struct window *w)
17612 {
17613
17614 static struct window *cwindow;
17615 static EMACS_INT window_ticks;
17616
17617
17618
17619
17620 if (!ticks && w != cwindow)
17621 {
17622 cwindow = w;
17623 window_ticks = 0;
17624 }
17625
17626
17627 if ((!w && !redisplaying_p && !display_working_on_window_p)
17628
17629
17630 || (w && MINI_WINDOW_P (w)))
17631 return;
17632
17633 if (ticks > 0)
17634 window_ticks += ticks;
17635 if (max_redisplay_ticks > 0 && window_ticks > max_redisplay_ticks)
17636 {
17637
17638
17639
17640 Lisp_Object contents = w ? w->contents : Qnil;
17641 char *bufname =
17642 NILP (contents)
17643 ? SSDATA (BVAR (current_buffer, name))
17644 : (BUFFERP (contents)
17645 ? SSDATA (BVAR (XBUFFER (contents), name))
17646 : (char *) "<unknown>");
17647
17648 windows_or_buffers_changed = 177;
17649
17650
17651
17652 if (w && w->desired_matrix)
17653 w->desired_matrix->no_scrolling_p = true;
17654 error ("Window showing buffer %s takes too long to redisplay", bufname);
17655 }
17656 }
17657
17658
17659
17660
17661
17662
17663
17664
17665
17666
17667 static bool
17668 set_cursor_from_row (struct window *w, struct glyph_row *row,
17669 struct glyph_matrix *matrix,
17670 ptrdiff_t delta, ptrdiff_t delta_bytes,
17671 int dy, int dvpos)
17672 {
17673 struct glyph *glyph = row->glyphs[TEXT_AREA];
17674 struct glyph *end = glyph + row->used[TEXT_AREA];
17675 struct glyph *cursor = NULL;
17676
17677 ptrdiff_t last_pos = MATRIX_ROW_START_CHARPOS (row) + delta;
17678 int x = row->x;
17679 ptrdiff_t pt_old = PT - delta;
17680 ptrdiff_t pos_before = MATRIX_ROW_START_CHARPOS (row) + delta;
17681 ptrdiff_t pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
17682 struct glyph *glyph_before = glyph - 1, *glyph_after = end;
17683
17684
17685 struct glyph *glyphs_end = end;
17686
17687
17688 bool match_with_avoid_cursor = false;
17689
17690
17691 bool string_seen = false;
17692
17693
17694 ptrdiff_t bpos_max = pos_before;
17695 ptrdiff_t bpos_min = pos_after;
17696
17697
17698 ptrdiff_t bpos_covered = 0;
17699
17700
17701 bool string_from_text_prop = false;
17702
17703
17704
17705
17706 eassert (!row->mode_line_p);
17707 if (row->mode_line_p)
17708 return false;
17709
17710
17711
17712
17713 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
17714 {
17715 if (!row->reversed_p)
17716 {
17717 while (glyph < end
17718 && NILP (glyph->object)
17719 && glyph->charpos < 0)
17720 {
17721 x += glyph->pixel_width;
17722 ++glyph;
17723 }
17724 while (end > glyph
17725 && NILP ((end - 1)->object)
17726
17727
17728 && (end - 1)->charpos <= 0)
17729 --end;
17730 glyph_before = glyph - 1;
17731 glyph_after = end;
17732 }
17733 else
17734 {
17735 struct glyph *g;
17736
17737
17738
17739 glyphs_end = end = glyph - 1;
17740 glyph += row->used[TEXT_AREA] - 1;
17741
17742 while (glyph > end + 1
17743 && NILP (glyph->object)
17744 && glyph->charpos < 0)
17745 --glyph;
17746 if (NILP (glyph->object) && glyph->charpos < 0)
17747 --glyph;
17748
17749
17750 for (x = 0, g = end + 1; g < glyph; g++)
17751 x += g->pixel_width;
17752 while (end < glyph
17753 && NILP ((end + 1)->object)
17754 && (end + 1)->charpos <= 0)
17755 ++end;
17756 glyph_before = glyph + 1;
17757 glyph_after = end;
17758 }
17759 }
17760 else if (row->reversed_p)
17761 {
17762
17763
17764
17765 cursor = end - 1;
17766
17767
17768
17769 if (!FRAME_WINDOW_P (WINDOW_XFRAME (w))
17770 && !WINDOW_RIGHTMOST_P (w)
17771 && cursor == row->glyphs[LAST_AREA] - 1)
17772 cursor--;
17773 x = -1;
17774 }
17775
17776
17777
17778
17779
17780 if (!row->reversed_p)
17781 while (
17782 glyph < end
17783
17784 && !NILP (glyph->object))
17785 {
17786 if (BUFFERP (glyph->object))
17787 {
17788 ptrdiff_t dpos = glyph->charpos - pt_old;
17789
17790 if (glyph->charpos > bpos_max)
17791 bpos_max = glyph->charpos;
17792 if (glyph->charpos < bpos_min)
17793 bpos_min = glyph->charpos;
17794 if (!glyph->avoid_cursor_p)
17795 {
17796
17797
17798 if (dpos == 0)
17799 {
17800 match_with_avoid_cursor = false;
17801 break;
17802 }
17803
17804
17805 if (0 > dpos && dpos > pos_before - pt_old)
17806 {
17807 pos_before = glyph->charpos;
17808 glyph_before = glyph;
17809 }
17810 else if (0 < dpos && dpos < pos_after - pt_old)
17811 {
17812 pos_after = glyph->charpos;
17813 glyph_after = glyph;
17814 }
17815 }
17816 else if (dpos == 0)
17817 match_with_avoid_cursor = true;
17818 }
17819 else if (STRINGP (glyph->object))
17820 {
17821 Lisp_Object chprop;
17822 ptrdiff_t glyph_pos = glyph->charpos;
17823
17824 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
17825 glyph->object);
17826 if (!NILP (chprop))
17827 {
17828
17829
17830
17831
17832
17833
17834
17835
17836
17837
17838 ptrdiff_t prop_pos =
17839 string_buffer_position_lim (glyph->object, pos_before,
17840 pos_after, false);
17841
17842 if (prop_pos >= pos_before)
17843 bpos_max = prop_pos;
17844 }
17845 if (FIXNUMP (chprop))
17846 {
17847 bpos_covered = bpos_max + XFIXNUM (chprop);
17848
17849
17850
17851
17852
17853
17854
17855
17856
17857
17858
17859 if (bpos_max <= pt_old && bpos_covered >= pt_old)
17860 {
17861 cursor = glyph;
17862 break;
17863 }
17864 }
17865
17866 string_seen = true;
17867 }
17868 x += glyph->pixel_width;
17869 ++glyph;
17870 }
17871 else if (glyph > end)
17872 while (!NILP (glyph->object))
17873 {
17874 if (BUFFERP (glyph->object))
17875 {
17876 ptrdiff_t dpos = glyph->charpos - pt_old;
17877
17878 if (glyph->charpos > bpos_max)
17879 bpos_max = glyph->charpos;
17880 if (glyph->charpos < bpos_min)
17881 bpos_min = glyph->charpos;
17882 if (!glyph->avoid_cursor_p)
17883 {
17884 if (dpos == 0)
17885 {
17886 match_with_avoid_cursor = false;
17887 break;
17888 }
17889 if (0 > dpos && dpos > pos_before - pt_old)
17890 {
17891 pos_before = glyph->charpos;
17892 glyph_before = glyph;
17893 }
17894 else if (0 < dpos && dpos < pos_after - pt_old)
17895 {
17896 pos_after = glyph->charpos;
17897 glyph_after = glyph;
17898 }
17899 }
17900 else if (dpos == 0)
17901 match_with_avoid_cursor = true;
17902 }
17903 else if (STRINGP (glyph->object))
17904 {
17905 Lisp_Object chprop;
17906 ptrdiff_t glyph_pos = glyph->charpos;
17907
17908 chprop = Fget_char_property (make_fixnum (glyph_pos), Qcursor,
17909 glyph->object);
17910 if (!NILP (chprop))
17911 {
17912 ptrdiff_t prop_pos =
17913 string_buffer_position_lim (glyph->object, pos_before,
17914 pos_after, false);
17915
17916 if (prop_pos >= pos_before)
17917 bpos_max = prop_pos;
17918 }
17919 if (FIXNUMP (chprop))
17920 {
17921 bpos_covered = bpos_max + XFIXNUM (chprop);
17922
17923
17924
17925 if (bpos_max <= pt_old && bpos_covered >= pt_old)
17926 {
17927 cursor = glyph;
17928 break;
17929 }
17930 }
17931 string_seen = true;
17932 }
17933 --glyph;
17934 if (glyph == glyphs_end)
17935 {
17936 x--;
17937 break;
17938 }
17939 x -= glyph->pixel_width;
17940 }
17941
17942
17943
17944
17945 if (!((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
17946 && BUFFERP (glyph->object) && glyph->charpos == pt_old)
17947 && !(bpos_max <= pt_old && pt_old <= bpos_covered))
17948 {
17949
17950
17951
17952
17953
17954 bool empty_line_p =
17955 ((row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end)
17956 && NILP (glyph->object) && glyph->charpos > 0
17957
17958
17959
17960
17961 && !(row->continued_p || row->truncated_on_right_p));
17962
17963 if (row->ends_in_ellipsis_p && pos_after == last_pos)
17964 {
17965 ptrdiff_t ellipsis_pos;
17966
17967
17968 if (!row->reversed_p)
17969 {
17970 ellipsis_pos = (glyph - 1)->charpos;
17971 while (glyph > row->glyphs[TEXT_AREA]
17972 && (glyph - 1)->charpos == ellipsis_pos)
17973 glyph--, x -= glyph->pixel_width;
17974
17975
17976
17977 x += glyph->pixel_width;
17978 glyph++;
17979 }
17980 else
17981 {
17982 ellipsis_pos = (glyph + 1)->charpos;
17983 while (glyph < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
17984 && (glyph + 1)->charpos == ellipsis_pos)
17985 glyph++, x += glyph->pixel_width;
17986 x -= glyph->pixel_width;
17987 glyph--;
17988 }
17989 }
17990 else if (match_with_avoid_cursor)
17991 {
17992 cursor = glyph_after;
17993 x = -1;
17994 }
17995 else if (string_seen)
17996 {
17997 int incr = row->reversed_p ? -1 : +1;
17998
17999
18000
18001
18002
18003
18004 struct glyph *start, *stop;
18005 ptrdiff_t pos = pos_before;
18006
18007 x = -1;
18008
18009
18010
18011
18012
18013
18014 if (row->ends_in_newline_from_string_p)
18015 {
18016 glyph_after = end;
18017 pos_after = MATRIX_ROW_END_CHARPOS (row) + delta;
18018 }
18019
18020
18021
18022
18023
18024
18025
18026
18027
18028 if (!row->reversed_p)
18029 {
18030 start = min (glyph_before, glyph_after);
18031 stop = max (glyph_before, glyph_after);
18032 }
18033 else
18034 {
18035 start = max (glyph_before, glyph_after);
18036 stop = min (glyph_before, glyph_after);
18037 }
18038 for (glyph = start + incr;
18039 row->reversed_p ? glyph > stop : glyph < stop; )
18040 {
18041
18042
18043
18044
18045 if (STRINGP (glyph->object))
18046 {
18047 Lisp_Object str;
18048 ptrdiff_t tem;
18049
18050
18051 ptrdiff_t lim = pos_after
18052 + (pos_after == MATRIX_ROW_END_CHARPOS (row) + delta);
18053
18054 string_from_text_prop = false;
18055 str = glyph->object;
18056 tem = string_buffer_position_lim (str, pos, lim, false);
18057 if (tem == 0
18058 || pos <= tem)
18059 {
18060
18061
18062
18063
18064
18065
18066
18067
18068
18069
18070 if (tem == 0
18071 || tem == pt_old
18072 || (tem - pt_old > 0 && tem < pos_after))
18073 {
18074
18075
18076
18077
18078
18079
18080 ptrdiff_t strpos = glyph->charpos;
18081
18082 if (tem)
18083 {
18084 cursor = glyph;
18085 string_from_text_prop = true;
18086 }
18087 for ( ;
18088 (row->reversed_p ? glyph > stop : glyph < stop)
18089 && EQ (glyph->object, str);
18090 glyph += incr)
18091 {
18092 Lisp_Object cprop;
18093 ptrdiff_t gpos = glyph->charpos;
18094
18095 cprop = Fget_char_property (make_fixnum (gpos),
18096 Qcursor,
18097 glyph->object);
18098 if (!NILP (cprop))
18099 {
18100 cursor = glyph;
18101 break;
18102 }
18103 if (tem && glyph->charpos < strpos)
18104 {
18105 strpos = glyph->charpos;
18106 cursor = glyph;
18107 }
18108 }
18109
18110 if (tem == pt_old
18111 || (tem - pt_old > 0 && tem < pos_after))
18112 goto compute_x;
18113 }
18114 if (tem)
18115 pos = tem + 1;
18116 }
18117
18118
18119 while ((row->reversed_p ? glyph > stop : glyph < stop)
18120 && EQ (glyph->object, str))
18121 glyph += incr;
18122 }
18123 else
18124 glyph += incr;
18125 }
18126
18127
18128
18129 if (cursor == NULL
18130 && (row->reversed_p ? glyph <= end : glyph >= end)
18131 && (row->reversed_p ? end > glyphs_end : end < glyphs_end)
18132 && STRINGP (end->object)
18133 && row->continued_p)
18134 return false;
18135 }
18136
18137
18138
18139
18140
18141 else if (row->truncated_on_left_p && pt_old < bpos_min)
18142 {
18143 cursor = glyph_before;
18144 x = -1;
18145 }
18146 else if ((row->truncated_on_right_p && pt_old > bpos_max)
18147
18148 || (!empty_line_p
18149 && (row->reversed_p
18150 ? glyph_after > glyphs_end
18151 : glyph_after < glyphs_end)))
18152 {
18153 cursor = glyph_after;
18154 x = -1;
18155 }
18156 }
18157
18158 compute_x:
18159 if (cursor != NULL)
18160 glyph = cursor;
18161 else if (glyph == glyphs_end
18162 && pos_before == pos_after
18163 && STRINGP ((row->reversed_p
18164 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18165 : row->glyphs[TEXT_AREA])->object))
18166 {
18167
18168
18169
18170
18171 glyph =
18172 row->reversed_p
18173 ? row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1
18174 : row->glyphs[TEXT_AREA];
18175 }
18176 if (x < 0)
18177 {
18178 struct glyph *g;
18179
18180
18181 for (g = row->glyphs[TEXT_AREA], x = row->x; g < glyph; g++)
18182 {
18183 if (g >= row->glyphs[TEXT_AREA] + row->used[TEXT_AREA])
18184 emacs_abort ();
18185 x += g->pixel_width;
18186 }
18187 }
18188
18189
18190
18191
18192
18193
18194 if (
18195 w->cursor.vpos >= 0
18196
18197 && MATRIX_ROW (matrix, w->cursor.vpos) != row
18198
18199
18200
18201
18202
18203 && MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos)) <= pt_old
18204 && pt_old <= MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18205 && cursor_row_p (MATRIX_ROW (matrix, w->cursor.vpos)))
18206 {
18207 struct glyph *g1
18208 = MATRIX_ROW_GLYPH_START (matrix, w->cursor.vpos) + w->cursor.hpos;
18209
18210
18211 if (!(row->reversed_p ? glyph > glyphs_end : glyph < glyphs_end))
18212 return false;
18213
18214
18215 if (
18216 w->cursor.hpos >= 0
18217 && w->cursor.hpos < MATRIX_ROW_USED (matrix, w->cursor.vpos)
18218 && ((BUFFERP (g1->object)
18219 && (g1->charpos == pt_old
18220 || (BUFFERP (glyph->object)
18221 && eabs (g1->charpos - pt_old)
18222 < eabs (glyph->charpos - pt_old))))
18223
18224
18225 || (STRINGP (g1->object)
18226 && (!NILP (Fget_char_property (make_fixnum (g1->charpos),
18227 Qcursor, g1->object))
18228
18229
18230
18231 || (EQ (g1->object, glyph->object)
18232 && string_from_text_prop)
18233
18234
18235 || (NILP (glyph->object)
18236 && glyph->charpos != pt_old)))))
18237 return false;
18238
18239 if (!((BUFFERP (glyph->object) && glyph->charpos == pt_old)
18240
18241
18242
18243 || (!row->continued_p
18244 && NILP (glyph->object)
18245 && glyph->charpos == 0
18246 && pt_old == MATRIX_ROW_END_CHARPOS (row) - 1))
18247
18248
18249
18250
18251
18252 && MATRIX_ROW_END_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18253 - MATRIX_ROW_START_CHARPOS (MATRIX_ROW (matrix, w->cursor.vpos))
18254 < MATRIX_ROW_END_CHARPOS (row) - MATRIX_ROW_START_CHARPOS (row))
18255 return false;
18256 }
18257 w->cursor.hpos = glyph - row->glyphs[TEXT_AREA];
18258 w->cursor.x = x;
18259 w->cursor.vpos = MATRIX_ROW_VPOS (row, matrix) + dvpos;
18260 w->cursor.y = row->y + dy;
18261
18262 if (w == XWINDOW (selected_window))
18263 {
18264 if (!row->continued_p
18265 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
18266 && row->x == 0)
18267 {
18268 this_line_buffer = XBUFFER (w->contents);
18269
18270 CHARPOS (this_line_start_pos)
18271 = MATRIX_ROW_START_CHARPOS (row) + delta;
18272 BYTEPOS (this_line_start_pos)
18273 = MATRIX_ROW_START_BYTEPOS (row) + delta_bytes;
18274
18275 CHARPOS (this_line_end_pos)
18276 = Z - (MATRIX_ROW_END_CHARPOS (row) + delta);
18277 BYTEPOS (this_line_end_pos)
18278 = Z_BYTE - (MATRIX_ROW_END_BYTEPOS (row) + delta_bytes);
18279
18280 this_line_y = w->cursor.y;
18281 this_line_pixel_height = row->height;
18282 this_line_vpos = w->cursor.vpos;
18283 this_line_start_x = row->x;
18284 }
18285 else
18286 CHARPOS (this_line_start_pos) = 0;
18287 }
18288
18289 return true;
18290 }
18291
18292
18293
18294
18295
18296
18297
18298 static struct text_pos
18299 run_window_scroll_functions (Lisp_Object window, struct text_pos startp)
18300 {
18301 struct window *w = XWINDOW (window);
18302 SET_MARKER_FROM_TEXT_POS (w->start, startp);
18303
18304 eassert (current_buffer == XBUFFER (w->contents));
18305
18306 if (!NILP (Vwindow_scroll_functions))
18307 {
18308 specpdl_ref count = SPECPDL_INDEX ();
18309 specbind (Qinhibit_quit, Qt);
18310 safe_run_hooks_2
18311 (Qwindow_scroll_functions, window, make_fixnum (CHARPOS (startp)));
18312 unbind_to (count, Qnil);
18313 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18314
18315 set_buffer_internal (XBUFFER (w->contents));
18316 }
18317
18318 return startp;
18319 }
18320
18321
18322
18323
18324
18325
18326
18327
18328
18329
18330
18331
18332
18333
18334
18335
18336
18337
18338
18339
18340
18341
18342 static bool
18343 cursor_row_fully_visible_p (struct window *w, bool force_p,
18344 bool current_matrix_p,
18345 bool just_test_user_preference_p)
18346 {
18347 struct glyph_matrix *matrix;
18348 struct glyph_row *row;
18349 int window_height;
18350 Lisp_Object mclfv_p =
18351 buffer_local_value (Qmake_cursor_line_fully_visible, w->contents);
18352
18353
18354 if (BASE_EQ (mclfv_p, Qunbound))
18355 mclfv_p = Vmake_cursor_line_fully_visible;
18356
18357
18358 if (FUNCTIONP (mclfv_p))
18359 {
18360 Lisp_Object window;
18361 XSETWINDOW (window, w);
18362
18363
18364 Lisp_Object val = safe_call1 (mclfv_p, window);
18365 if (NILP (val))
18366 return true;
18367 else if (just_test_user_preference_p)
18368 return false;
18369 }
18370 else if (NILP (mclfv_p))
18371 return true;
18372 else if (just_test_user_preference_p)
18373 return false;
18374
18375
18376
18377 if (w->cursor.vpos < 0)
18378 return true;
18379
18380 matrix = current_matrix_p ? w->current_matrix : w->desired_matrix;
18381 row = MATRIX_ROW (matrix, w->cursor.vpos);
18382
18383
18384 if (!MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row))
18385 return true;
18386
18387
18388
18389 window_height = window_box_height (w);
18390 if (row->height >= window_height)
18391 {
18392 if (!force_p || MINI_WINDOW_P (w)
18393 || w->vscroll || w->cursor.vpos == 0)
18394 return true;
18395 }
18396 return false;
18397 }
18398
18399
18400
18401
18402
18403
18404
18405
18406
18407
18408
18409
18410
18411
18412
18413
18414
18415
18416
18417
18418 enum
18419 {
18420 SCROLLING_SUCCESS = 1,
18421 SCROLLING_FAILED = 0,
18422 SCROLLING_NEED_LARGER_MATRICES = -1
18423 };
18424
18425
18426
18427
18428
18429 #define SCROLL_LIMIT 100
18430
18431 static int
18432 try_scrolling (Lisp_Object window, bool just_this_one_p,
18433 intmax_t arg_scroll_conservatively, intmax_t scroll_step,
18434 bool temp_scroll_step, bool last_line_misfit)
18435 {
18436 struct window *w = XWINDOW (window);
18437 struct text_pos pos, startp;
18438 struct it it;
18439 int this_scroll_margin, scroll_max, rc, height;
18440 int dy = 0, amount_to_scroll = 0;
18441 bool scroll_down_p = false;
18442 int extra_scroll_margin_lines = last_line_misfit;
18443 Lisp_Object aggressive;
18444
18445 int scroll_limit = SCROLL_LIMIT;
18446 int frame_line_height = default_line_pixel_height (w);
18447
18448 #ifdef GLYPH_DEBUG
18449 debug_method_add (w, "try_scrolling");
18450 #endif
18451
18452 SET_TEXT_POS_FROM_MARKER (startp, w->start);
18453
18454 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18455
18456
18457
18458
18459
18460 if (arg_scroll_conservatively > scroll_limit)
18461 {
18462 arg_scroll_conservatively = scroll_limit + 1;
18463 scroll_max = scroll_limit * frame_line_height;
18464 }
18465 else if (0 < scroll_step || 0 < arg_scroll_conservatively || temp_scroll_step)
18466
18467
18468 {
18469 intmax_t scroll_lines_max
18470 = max (scroll_step, max (arg_scroll_conservatively, temp_scroll_step));
18471 int scroll_lines = clip_to_bounds (0, scroll_lines_max, 1000000);
18472 scroll_max = scroll_lines * frame_line_height;
18473 }
18474 else if (NUMBERP (BVAR (current_buffer, scroll_down_aggressively))
18475 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively)))
18476
18477
18478 scroll_max = 10 * frame_line_height;
18479 else
18480 scroll_max = 0;
18481
18482 too_near_end:
18483
18484
18485 if (PT > CHARPOS (startp))
18486 {
18487 int scroll_margin_y;
18488
18489
18490
18491 start_display (&it, w, startp);
18492 scroll_margin_y = it.last_visible_y - partial_line_height (&it)
18493 - this_scroll_margin
18494 - frame_line_height * extra_scroll_margin_lines;
18495 move_it_to (&it, PT, -1, scroll_margin_y - 1, -1,
18496 (MOVE_TO_POS | MOVE_TO_Y));
18497
18498 if (PT > CHARPOS (it.current.pos))
18499 {
18500 int y0 = line_bottom_y (&it);
18501
18502
18503
18504
18505
18506 int slack = max (scroll_max, 10 * frame_line_height);
18507 int y_to_move = it.last_visible_y + slack;
18508
18509
18510
18511
18512
18513 move_it_to (&it, PT, -1, y_to_move,
18514 -1, MOVE_TO_POS | MOVE_TO_Y);
18515 dy = line_bottom_y (&it) - y0;
18516
18517 if (dy > scroll_max)
18518 return SCROLLING_FAILED;
18519
18520 if (dy > 0)
18521 scroll_down_p = true;
18522 }
18523 else if (PT == IT_CHARPOS (it)
18524 && IT_CHARPOS (it) < ZV
18525 && it.method == GET_FROM_STRING
18526 && arg_scroll_conservatively > scroll_limit
18527 && it.current_x == 0)
18528 {
18529 enum move_it_result skip;
18530 int y1 = it.current_y;
18531 int vpos;
18532
18533
18534
18535
18536
18537
18538
18539 do {
18540 skip = move_it_in_display_line_to (&it, ZV, -1, MOVE_TO_POS);
18541 if (skip != MOVE_NEWLINE_OR_CR
18542 || IT_CHARPOS (it) != PT
18543 || it.method == GET_FROM_BUFFER)
18544 break;
18545 vpos = it.vpos;
18546 move_it_to (&it, -1, -1, -1, vpos + 1, MOVE_TO_VPOS);
18547 } while (it.vpos > vpos);
18548
18549 dy = it.current_y - y1;
18550
18551 if (dy > scroll_max)
18552 return SCROLLING_FAILED;
18553
18554 if (dy > 0)
18555 scroll_down_p = true;
18556 }
18557 }
18558
18559 if (scroll_down_p)
18560 {
18561
18562
18563
18564
18565 if (arg_scroll_conservatively)
18566 amount_to_scroll
18567 = min (max (dy, frame_line_height),
18568 frame_line_height * arg_scroll_conservatively);
18569 else if (scroll_step || temp_scroll_step)
18570 amount_to_scroll = scroll_max;
18571 else
18572 {
18573 aggressive = BVAR (current_buffer, scroll_up_aggressively);
18574 height = WINDOW_BOX_TEXT_HEIGHT (w);
18575 if (NUMBERP (aggressive))
18576 {
18577 double float_amount = XFLOATINT (aggressive) * height;
18578 int aggressive_scroll = float_amount;
18579 if (aggressive_scroll == 0 && float_amount > 0)
18580 aggressive_scroll = 1;
18581
18582
18583
18584
18585
18586
18587 if (aggressive_scroll + 2 * this_scroll_margin > height)
18588 aggressive_scroll = height - 2 * this_scroll_margin;
18589 amount_to_scroll = dy + aggressive_scroll;
18590 }
18591 }
18592
18593 if (amount_to_scroll <= 0)
18594 return SCROLLING_FAILED;
18595
18596 start_display (&it, w, startp);
18597 if (arg_scroll_conservatively <= scroll_limit)
18598 move_it_vertically (&it, amount_to_scroll);
18599 else
18600 {
18601
18602
18603
18604
18605
18606
18607 struct it it1;
18608 void *it1data = NULL;
18609
18610
18611 int start_y;
18612
18613 SAVE_IT (it1, it, it1data);
18614 start_y = line_bottom_y (&it1);
18615 do {
18616 RESTORE_IT (&it, &it, it1data);
18617 move_it_by_lines (&it, 1);
18618 SAVE_IT (it1, it, it1data);
18619 } while (IT_CHARPOS (it) < ZV
18620 && line_bottom_y (&it1) - start_y < amount_to_scroll);
18621 bidi_unshelve_cache (it1data, true);
18622 }
18623
18624
18625 if (IT_CHARPOS (it) == CHARPOS (startp))
18626 move_it_by_lines (&it, 1);
18627 startp = it.current.pos;
18628 }
18629 else
18630 {
18631 struct text_pos scroll_margin_pos = startp;
18632 int y_offset = 0;
18633
18634
18635
18636 if (this_scroll_margin)
18637 {
18638 int y_start;
18639
18640 start_display (&it, w, startp);
18641 y_start = it.current_y;
18642 move_it_vertically (&it, this_scroll_margin);
18643 scroll_margin_pos = it.current.pos;
18644
18645
18646
18647 if (IT_CHARPOS (it) == ZV
18648 && it.current_y - y_start < this_scroll_margin)
18649 y_offset = this_scroll_margin - (it.current_y - y_start);
18650 }
18651
18652 if (PT < CHARPOS (scroll_margin_pos))
18653 {
18654
18655
18656 int y0, y_to_move;
18657
18658
18659
18660
18661
18662
18663 SET_TEXT_POS (pos, PT, PT_BYTE);
18664 start_display (&it, w, pos);
18665 y0 = it.current_y;
18666 y_to_move = max (it.last_visible_y,
18667 max (scroll_max, 10 * frame_line_height));
18668 move_it_to (&it, CHARPOS (scroll_margin_pos), 0,
18669 y_to_move, -1,
18670 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18671 dy = it.current_y - y0;
18672 if (dy > scroll_max
18673 || IT_CHARPOS (it) < CHARPOS (scroll_margin_pos))
18674 return SCROLLING_FAILED;
18675
18676
18677 dy += y_offset;
18678
18679
18680 start_display (&it, w, startp);
18681
18682 if (arg_scroll_conservatively)
18683 amount_to_scroll
18684 = min (max (dy, frame_line_height),
18685 frame_line_height * arg_scroll_conservatively);
18686 else if (scroll_step || temp_scroll_step)
18687 amount_to_scroll = scroll_max;
18688 else
18689 {
18690 aggressive = BVAR (current_buffer, scroll_down_aggressively);
18691 height = WINDOW_BOX_TEXT_HEIGHT (w);
18692 if (NUMBERP (aggressive))
18693 {
18694 double float_amount = XFLOATINT (aggressive) * height;
18695 int aggressive_scroll = float_amount;
18696 if (aggressive_scroll == 0 && float_amount > 0)
18697 aggressive_scroll = 1;
18698
18699
18700
18701
18702 if (aggressive_scroll + 2 * this_scroll_margin > height)
18703 aggressive_scroll = height - 2 * this_scroll_margin;
18704 amount_to_scroll = dy + aggressive_scroll;
18705 }
18706 }
18707
18708 if (amount_to_scroll <= 0)
18709 return SCROLLING_FAILED;
18710
18711 move_it_vertically_backward (&it, amount_to_scroll);
18712 startp = it.current.pos;
18713 }
18714 }
18715
18716
18717 startp = run_window_scroll_functions (window, startp);
18718
18719
18720
18721 if (!try_window (window, startp, 0))
18722 rc = SCROLLING_NEED_LARGER_MATRICES;
18723 else if (w->cursor.vpos < 0)
18724 {
18725 clear_glyph_matrix (w->desired_matrix);
18726 rc = SCROLLING_FAILED;
18727 }
18728 else
18729 {
18730
18731 if (!just_this_one_p
18732 || current_buffer->clip_changed
18733 || BEG_UNCHANGED < CHARPOS (startp))
18734 w->base_line_number = 0;
18735
18736
18737
18738 if (! cursor_row_fully_visible_p (w, extra_scroll_margin_lines <= 1,
18739 false, false)
18740
18741
18742
18743 && extra_scroll_margin_lines < w->desired_matrix->nrows - 1)
18744 {
18745 clear_glyph_matrix (w->desired_matrix);
18746 ++extra_scroll_margin_lines;
18747 goto too_near_end;
18748 }
18749 rc = SCROLLING_SUCCESS;
18750 }
18751
18752 return rc;
18753 }
18754
18755
18756
18757
18758
18759
18760
18761
18762
18763
18764
18765
18766 static bool
18767 compute_window_start_on_continuation_line (struct window *w)
18768 {
18769 struct text_pos pos, start_pos, pos_before_pt;
18770 bool window_start_changed_p = false;
18771
18772 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
18773
18774
18775
18776
18777 if (CHARPOS (start_pos) > BEGV
18778 && FETCH_BYTE (BYTEPOS (start_pos) - 1) != '\n')
18779 {
18780 struct it it;
18781 struct glyph_row *row;
18782
18783
18784 if (CHARPOS (start_pos) < BEGV)
18785 SET_TEXT_POS (start_pos, BEGV, BEGV_BYTE);
18786 else if (CHARPOS (start_pos) > ZV)
18787 SET_TEXT_POS (start_pos, ZV, ZV_BYTE);
18788
18789
18790
18791 row = w->desired_matrix->rows + window_wants_tab_line (w)
18792 + window_wants_header_line (w);
18793 init_iterator (&it, w, CHARPOS (start_pos), BYTEPOS (start_pos),
18794 row, DEFAULT_FACE_ID);
18795 reseat_at_previous_visible_line_start (&it);
18796
18797
18798
18799
18800
18801
18802
18803 if (IT_CHARPOS (it) <= PT
18804 && (CHARPOS (start_pos) - IT_CHARPOS (it)
18805
18806 < WINDOW_TOTAL_LINES (w) * WINDOW_TOTAL_COLS (w)))
18807 {
18808 int min_distance, distance;
18809
18810
18811
18812
18813
18814
18815
18816 pos_before_pt = pos = it.current.pos;
18817 min_distance = DISP_INFINITY;
18818 while ((distance = eabs (CHARPOS (start_pos) - IT_CHARPOS (it))),
18819 distance < min_distance)
18820 {
18821 min_distance = distance;
18822 if (CHARPOS (pos) <= PT)
18823 pos_before_pt = pos;
18824 pos = it.current.pos;
18825 if (it.line_wrap == WORD_WRAP)
18826 {
18827
18828
18829
18830
18831
18832
18833
18834
18835
18836 move_it_to (&it, ZV, it.last_visible_x, it.current_y, -1,
18837 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18838 move_it_to (&it, ZV, 0,
18839 it.current_y + it.max_ascent + it.max_descent, -1,
18840 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
18841 }
18842 else
18843 move_it_by_lines (&it, 1);
18844 }
18845
18846
18847
18848
18849
18850 if (CHARPOS (pos) > PT)
18851 pos = pos_before_pt;
18852
18853
18854 SET_MARKER_FROM_TEXT_POS (w->start, pos);
18855 window_start_changed_p = true;
18856 }
18857 }
18858
18859 return window_start_changed_p;
18860 }
18861
18862
18863
18864
18865
18866
18867
18868
18869
18870
18871
18872
18873
18874
18875
18876
18877
18878 enum
18879 {
18880 CURSOR_MOVEMENT_SUCCESS,
18881 CURSOR_MOVEMENT_CANNOT_BE_USED,
18882 CURSOR_MOVEMENT_MUST_SCROLL,
18883 CURSOR_MOVEMENT_NEED_LARGER_MATRICES
18884 };
18885
18886 static int
18887 try_cursor_movement (Lisp_Object window, struct text_pos startp,
18888 bool *scroll_step)
18889 {
18890 struct window *w = XWINDOW (window);
18891 struct frame *f = XFRAME (w->frame);
18892 int rc = CURSOR_MOVEMENT_CANNOT_BE_USED;
18893
18894 #ifdef GLYPH_DEBUG
18895 if (inhibit_try_cursor_movement)
18896 return rc;
18897 #endif
18898
18899
18900
18901
18902 eassert (w->last_point > 0);
18903
18904
18905
18906 eassert (!w->window_end_valid
18907 || w->window_end_vpos < w->current_matrix->nrows);
18908
18909
18910
18911 if (
18912 PT >= CHARPOS (startp)
18913
18914 && !current_buffer->clip_changed
18915
18916
18917
18918
18919 && !update_mode_lines
18920 && !windows_or_buffers_changed
18921 && !f->cursor_type_changed
18922 && NILP (Vshow_trailing_whitespace)
18923
18924
18925 && !EQ (Vdisplay_line_numbers, Qrelative)
18926 && !EQ (Vdisplay_line_numbers, Qvisual)
18927
18928
18929
18930 && !(!NILP (Vdisplay_line_numbers)
18931 && NILP (Finternal_lisp_face_equal_p (Qline_number,
18932 Qline_number_current_line,
18933 w->frame)))
18934
18935
18936
18937
18938
18939
18940 && !EQ (window, minibuf_window)
18941
18942
18943
18944 && !overlay_arrow_in_current_buffer_p ())
18945 {
18946 int this_scroll_margin, top_scroll_margin;
18947 struct glyph_row *row = NULL;
18948
18949 #ifdef GLYPH_DEBUG
18950 debug_method_add (w, "cursor movement");
18951 #endif
18952
18953 this_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
18954
18955 top_scroll_margin = this_scroll_margin;
18956 if (window_wants_tab_line (w))
18957 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
18958 if (window_wants_header_line (w))
18959 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
18960
18961
18962
18963 if (w->last_cursor_vpos < 0
18964 || w->last_cursor_vpos >= w->current_matrix->nrows)
18965 rc = CURSOR_MOVEMENT_MUST_SCROLL;
18966 else
18967 {
18968 row = MATRIX_ROW (w->current_matrix, w->last_cursor_vpos);
18969
18970 if (row->tab_line_p)
18971 ++row;
18972 if (row->mode_line_p)
18973 ++row;
18974 if (!row->enabled_p)
18975 rc = CURSOR_MOVEMENT_MUST_SCROLL;
18976 }
18977
18978 if (rc == CURSOR_MOVEMENT_CANNOT_BE_USED)
18979 {
18980 bool scroll_p = false, must_scroll = false;
18981 int last_y = window_text_bottom_y (w) - this_scroll_margin;
18982
18983 if (PT > w->last_point)
18984 {
18985
18986 while (MATRIX_ROW_END_CHARPOS (row) < PT
18987 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
18988 {
18989 eassert (row->enabled_p);
18990 ++row;
18991 }
18992
18993
18994
18995
18996 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
18997 && MATRIX_ROW_END_CHARPOS (row) == PT
18998 && row < MATRIX_MODE_LINE_ROW (w->current_matrix)
18999 && MATRIX_ROW_START_CHARPOS (row+1) >= PT
19000 && !cursor_row_p (row))
19001 ++row;
19002
19003
19004
19005
19006
19007 if (MATRIX_ROW_BOTTOM_Y (row) > last_y
19008 || PT > MATRIX_ROW_END_CHARPOS (row)
19009
19010
19011 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19012 && PT == MATRIX_ROW_END_CHARPOS (row)
19013 && !row->ends_at_zv_p
19014 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19015 scroll_p = true;
19016 }
19017 else if (PT < w->last_point)
19018 {
19019
19020
19021 struct glyph_row *row0 = row;
19022
19023 while (!row->mode_line_p
19024 && (MATRIX_ROW_START_CHARPOS (row) > PT
19025 || (MATRIX_ROW_START_CHARPOS (row) == PT
19026 && (MATRIX_ROW_STARTS_IN_MIDDLE_OF_CHAR_P (row)
19027 || (
19028 row > w->current_matrix->rows
19029 && (row-1)->ends_in_newline_from_string_p))))
19030 && (row->y > top_scroll_margin
19031 || CHARPOS (startp) == BEGV))
19032 {
19033 eassert (row->enabled_p);
19034 --row;
19035 }
19036
19037
19038
19039
19040
19041 if (!(MATRIX_ROW_START_CHARPOS (row) <= PT
19042 && PT <= MATRIX_ROW_END_CHARPOS (row))
19043 && row0->continued_p)
19044 {
19045 row = row0;
19046 while (MATRIX_ROW_START_CHARPOS (row) > PT
19047 && MATRIX_ROW_BOTTOM_Y (row) < last_y)
19048 {
19049 eassert (row->enabled_p);
19050 ++row;
19051 }
19052 }
19053
19054
19055
19056
19057
19058
19059 if (row < w->current_matrix->rows
19060 || row->mode_line_p)
19061 {
19062 row = w->current_matrix->rows;
19063
19064 if (row->tab_line_p)
19065 ++row;
19066 if (row->mode_line_p)
19067 ++row;
19068 }
19069
19070
19071
19072 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19073 && MATRIX_ROW_END_CHARPOS (row) == PT
19074 && !cursor_row_p (row))
19075 ++row;
19076
19077
19078
19079 if ((row->y < top_scroll_margin
19080 && CHARPOS (startp) != BEGV)
19081 || MATRIX_ROW_BOTTOM_Y (row) > last_y
19082 || PT > MATRIX_ROW_END_CHARPOS (row)
19083 || (MATRIX_ROW_BOTTOM_Y (row) == last_y
19084 && PT == MATRIX_ROW_END_CHARPOS (row)
19085 && !row->ends_at_zv_p
19086 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
19087 scroll_p = true;
19088 }
19089 else
19090 {
19091
19092
19093 rc = CURSOR_MOVEMENT_SUCCESS;
19094 }
19095
19096 if ((PT < MATRIX_ROW_START_CHARPOS (row)
19097 && (row == MATRIX_FIRST_TEXT_ROW (w->current_matrix)
19098
19099
19100 || (MATRIX_ROW_END_CHARPOS (row-1)
19101 == MATRIX_ROW_START_CHARPOS (row))))
19102 || PT > MATRIX_ROW_END_CHARPOS (row))
19103 {
19104
19105 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19106 must_scroll = true;
19107 }
19108 else if (rc != CURSOR_MOVEMENT_SUCCESS
19109 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19110 {
19111 struct glyph_row *row1;
19112
19113
19114
19115
19116
19117
19118
19119
19120
19121
19122
19123 for (row1 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
19124 MATRIX_ROW_CONTINUATION_LINE_P (row);
19125 --row)
19126 {
19127
19128
19129
19130 if (row <= row1)
19131 {
19132 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19133 break;
19134 }
19135 eassert (row->enabled_p);
19136 }
19137 }
19138 if (must_scroll)
19139 ;
19140 else if (rc != CURSOR_MOVEMENT_SUCCESS
19141 && MATRIX_ROW_PARTIALLY_VISIBLE_P (w, row)
19142
19143
19144
19145 && !row->mode_line_p
19146 && !cursor_row_fully_visible_p (w, true, true, true))
19147 {
19148 if (PT == MATRIX_ROW_END_CHARPOS (row)
19149 && !row->ends_at_zv_p
19150 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
19151 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19152 else if (row->height > window_box_height (w))
19153 {
19154
19155
19156
19157
19158 *scroll_step = true;
19159 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19160 }
19161 else
19162 {
19163 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
19164 if (!cursor_row_fully_visible_p (w, false, true, false))
19165 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19166 else
19167 rc = CURSOR_MOVEMENT_SUCCESS;
19168 }
19169 }
19170 else if (scroll_p)
19171 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19172 else if (rc != CURSOR_MOVEMENT_SUCCESS
19173 && !NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
19174 {
19175
19176
19177
19178
19179
19180
19181
19182 bool rv = false;
19183 bool pt_invis = false;
19184 Lisp_Object val = get_char_property_and_overlay (make_fixnum (PT),
19185 Qinvisible,
19186 Qnil, NULL);
19187
19188 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
19189 pt_invis = true;
19190
19191 do
19192 {
19193 bool at_zv_p = false, exact_match_p = false;
19194
19195
19196
19197
19198
19199 if ((pt_invis || MATRIX_ROW_START_CHARPOS (row) <= PT)
19200 && PT <= MATRIX_ROW_END_CHARPOS (row)
19201 && cursor_row_p (row))
19202 rv |= set_cursor_from_row (w, row, w->current_matrix,
19203 0, 0, 0, 0);
19204
19205
19206
19207 if (rv)
19208 {
19209 at_zv_p = MATRIX_ROW (w->current_matrix,
19210 w->cursor.vpos)->ends_at_zv_p;
19211 if (!at_zv_p
19212 && w->cursor.hpos >= 0
19213 && w->cursor.hpos < MATRIX_ROW_USED (w->current_matrix,
19214 w->cursor.vpos))
19215 {
19216 struct glyph_row *candidate =
19217 MATRIX_ROW (w->current_matrix, w->cursor.vpos);
19218 struct glyph *g =
19219 candidate->glyphs[TEXT_AREA] + w->cursor.hpos;
19220 ptrdiff_t endpos = MATRIX_ROW_END_CHARPOS (candidate);
19221
19222 exact_match_p =
19223 (BUFFERP (g->object) && g->charpos == PT)
19224 || (NILP (g->object)
19225 && (g->charpos == PT
19226 || (g->charpos == 0 && endpos - 1 == PT)));
19227
19228
19229
19230
19231 if (!exact_match_p && pt_invis)
19232 exact_match_p = true;
19233 }
19234 if (at_zv_p || exact_match_p)
19235 {
19236 rc = CURSOR_MOVEMENT_SUCCESS;
19237 break;
19238 }
19239 }
19240 if (MATRIX_ROW_BOTTOM_Y (row) == last_y)
19241 break;
19242 ++row;
19243 }
19244 while (((MATRIX_ROW_CONTINUATION_LINE_P (row)
19245 || row->continued_p)
19246 && MATRIX_ROW_BOTTOM_Y (row) <= last_y)
19247 || (MATRIX_ROW_START_CHARPOS (row) == PT
19248 && MATRIX_ROW_BOTTOM_Y (row) < last_y));
19249
19250
19251
19252 if (rc != CURSOR_MOVEMENT_SUCCESS
19253 && !(rv
19254 && !MATRIX_ROW_CONTINUATION_LINE_P (row)
19255 && !row->continued_p))
19256 rc = CURSOR_MOVEMENT_MUST_SCROLL;
19257 else if (rv)
19258 rc = CURSOR_MOVEMENT_SUCCESS;
19259 }
19260 else
19261 {
19262 do
19263 {
19264 if (set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0))
19265 {
19266 rc = CURSOR_MOVEMENT_SUCCESS;
19267 break;
19268 }
19269 ++row;
19270 }
19271 while (MATRIX_ROW_BOTTOM_Y (row) < last_y
19272 && MATRIX_ROW_START_CHARPOS (row) == PT
19273 && cursor_row_p (row));
19274 }
19275 }
19276 }
19277
19278 return rc;
19279 }
19280
19281
19282 void
19283 set_vertical_scroll_bar (struct window *w)
19284 {
19285 ptrdiff_t start, end, whole;
19286
19287
19288
19289
19290
19291
19292
19293
19294 if (!MINI_WINDOW_P (w)
19295 || (w == XWINDOW (minibuf_window)
19296 && NILP (echo_area_buffer[0])))
19297 {
19298 struct buffer *buf = XBUFFER (w->contents);
19299
19300 whole = BUF_ZV (buf) - BUF_BEGV (buf);
19301 start = marker_position (w->start) - BUF_BEGV (buf);
19302 end = BUF_Z (buf) - w->window_end_pos - BUF_BEGV (buf);
19303
19304
19305
19306
19307 if (!w->window_end_valid && !buf->long_line_optimizations_p)
19308 {
19309 struct it it;
19310 struct text_pos start_pos;
19311 struct buffer *obuf = current_buffer;
19312
19313
19314
19315 set_buffer_internal_1 (XBUFFER (w->contents));
19316 SET_TEXT_POS_FROM_MARKER (start_pos, w->start);
19317 start_display (&it, w, start_pos);
19318 move_it_to (&it, -1, it.last_visible_x, window_box_height (w), -1,
19319 MOVE_TO_X | MOVE_TO_Y);
19320 end -= (BUF_Z (buf) - IT_CHARPOS (it)) - w->window_end_pos;
19321 set_buffer_internal_1 (obuf);
19322 }
19323
19324 if (end < start)
19325 end = start;
19326 if (whole < (end - start))
19327 whole = end - start;
19328 }
19329 else
19330 start = end = whole = 0;
19331
19332
19333 if (FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19334 (*FRAME_TERMINAL (XFRAME (w->frame))->set_vertical_scroll_bar_hook)
19335 (w, end - start, whole, start);
19336 }
19337
19338
19339 void
19340 set_horizontal_scroll_bar (struct window *w)
19341 {
19342 int start, end, whole, portion;
19343
19344 if (!MINI_WINDOW_P (w) || EQ (w->horizontal_scroll_bar_type, Qbottom))
19345 {
19346 struct buffer *b = XBUFFER (w->contents);
19347 struct buffer *old_buffer = NULL;
19348 struct it it;
19349 struct text_pos startp;
19350
19351 if (b != current_buffer)
19352 {
19353 old_buffer = current_buffer;
19354 set_buffer_internal (b);
19355 }
19356
19357 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19358 start_display (&it, w, startp);
19359 it.last_visible_x = INT_MAX;
19360 whole = move_it_to (&it, -1, INT_MAX, window_box_height (w), -1,
19361 MOVE_TO_X | MOVE_TO_Y);
19362
19363
19364
19365
19366 start = w->hscroll * FRAME_COLUMN_WIDTH (WINDOW_XFRAME (w));
19367 end = start + window_box_width (w, TEXT_AREA);
19368 portion = end - start;
19369
19370
19371
19372
19373 whole = max (whole, end);
19374
19375 if (it.bidi_p)
19376 {
19377 Lisp_Object pdir;
19378
19379 pdir = Fcurrent_bidi_paragraph_direction (Qnil);
19380 if (EQ (pdir, Qright_to_left))
19381 {
19382 start = whole - end;
19383 end = start + portion;
19384 }
19385 }
19386
19387 if (old_buffer)
19388 set_buffer_internal (old_buffer);
19389 }
19390 else
19391 start = end = whole = portion = 0;
19392
19393 w->hscroll_whole = whole;
19394
19395
19396 if (FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19397 (*FRAME_TERMINAL (XFRAME (w->frame))->set_horizontal_scroll_bar_hook)
19398 (w, portion, whole, start);
19399 }
19400
19401
19402
19403 static bool
19404 window_start_acceptable_p (Lisp_Object window, ptrdiff_t startp)
19405 {
19406 if (!make_window_start_visible)
19407 return true;
19408
19409 struct window *w = XWINDOW (window);
19410 struct frame *f = XFRAME (w->frame);
19411 Lisp_Object startpos = make_fixnum (startp);
19412 Lisp_Object invprop, disp_spec;
19413 struct text_pos ignored;
19414
19415
19416 if ((invprop = Fget_char_property (startpos, Qinvisible, window)),
19417 TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19418 return false;
19419
19420
19421 if (!NILP (disp_spec = Fget_char_property (startpos, Qdisplay, window))
19422 && handle_display_spec (NULL, disp_spec, Qnil, Qnil, &ignored, startp,
19423 FRAME_WINDOW_P (f)) > 0)
19424 return false;
19425
19426 return true;
19427 }
19428
19429 DEFUN ("long-line-optimizations-p", Flong_line_optimizations_p, Slong_line_optimizations_p,
19430 0, 0, 0,
19431 doc:
19432
19433 )
19434 (void)
19435 {
19436 return current_buffer->long_line_optimizations_p ? Qt : Qnil;
19437 }
19438
19439
19440
19441
19442
19443
19444
19445
19446
19447
19448
19449
19450
19451
19452
19453
19454
19455
19456
19457
19458
19459
19460
19461
19462
19463
19464
19465
19466
19467
19468
19469
19470
19471
19472
19473
19474
19475
19476
19477
19478
19479
19480
19481
19482
19483
19484
19485
19486
19487
19488
19489 static void
19490 redisplay_window (Lisp_Object window, bool just_this_one_p)
19491 {
19492 struct window *w = XWINDOW (window);
19493 struct frame *f = XFRAME (w->frame);
19494 struct buffer *buffer = XBUFFER (w->contents);
19495 struct buffer *old = current_buffer;
19496 struct text_pos lpoint, opoint, startp;
19497 bool update_mode_line;
19498 int tem;
19499 struct it it;
19500
19501 bool current_matrix_up_to_date_p = false;
19502 bool used_current_matrix_p = false;
19503
19504
19505 bool buffer_unchanged_p = false;
19506 bool temp_scroll_step = false;
19507 specpdl_ref count = SPECPDL_INDEX ();
19508 int rc;
19509 int centering_position = -1;
19510 bool last_line_misfit = false;
19511 ptrdiff_t beg_unchanged, end_unchanged;
19512 int frame_line_height, margin;
19513 bool use_desired_matrix;
19514 void *itdata = NULL;
19515
19516 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19517 opoint = lpoint;
19518
19519 #ifdef GLYPH_DEBUG
19520 *w->desired_matrix->method = 0;
19521 #endif
19522
19523 if (!just_this_one_p && needs_no_redisplay (w))
19524 return;
19525
19526
19527 eassert (XMARKER (w->start)->buffer == buffer);
19528 eassert (XMARKER (w->pointm)->buffer == buffer);
19529
19530 reconsider_clip_changes (w);
19531 frame_line_height = default_line_pixel_height (w);
19532 margin = window_scroll_margin (w, MARGIN_IN_LINES);
19533
19534
19535
19536 update_mode_line = (w->update_mode_line
19537 || update_mode_lines
19538 || buffer->clip_changed
19539 || buffer->prevent_redisplay_optimizations_p);
19540
19541 if (!just_this_one_p)
19542
19543
19544 w->must_be_updated_p = true;
19545
19546 if (MINI_WINDOW_P (w))
19547 {
19548 if (w == XWINDOW (echo_area_window)
19549 && !NILP (echo_area_buffer[0]))
19550 {
19551 if (update_mode_line)
19552
19553
19554 goto finish_menu_bars;
19555 else
19556
19557 goto finish_scroll_bars;
19558 }
19559 else if ((w != XWINDOW (minibuf_window)
19560 || minibuf_level == 0)
19561
19562 && BUF_Z (XBUFFER (w->contents)) == BUF_BEG (XBUFFER (w->contents))
19563
19564
19565 && !NILP (Fmemq (w->contents, Vminibuffer_list)))
19566 {
19567
19568
19569 int yb = window_text_bottom_y (w);
19570 struct glyph_row *row;
19571 int y;
19572
19573 for (y = 0, row = w->desired_matrix->rows;
19574 y < yb;
19575 y += row->height, ++row)
19576 blank_row (w, row, y);
19577 goto finish_scroll_bars;
19578 }
19579 else if (minibuf_level >= 1)
19580 {
19581
19582
19583
19584 resize_mini_window (w, false);
19585 }
19586
19587 clear_glyph_matrix (w->desired_matrix);
19588 }
19589
19590
19591
19592
19593
19594 set_buffer_internal_1 (XBUFFER (w->contents));
19595
19596 current_matrix_up_to_date_p
19597 = (w->window_end_valid
19598 && !current_buffer->clip_changed
19599 && !current_buffer->prevent_redisplay_optimizations_p
19600 && !window_outdated (w)
19601 && !composition_break_at_point
19602 && !hscrolling_current_line_p (w));
19603
19604 beg_unchanged = BEG_UNCHANGED;
19605 end_unchanged = END_UNCHANGED;
19606
19607 SET_TEXT_POS (opoint, PT, PT_BYTE);
19608
19609 specbind (Qinhibit_point_motion_hooks, Qt);
19610
19611 buffer_unchanged_p
19612 = (w->window_end_valid
19613 && !current_buffer->clip_changed
19614 && !window_outdated (w));
19615
19616
19617
19618 if (windows_or_buffers_changed)
19619 {
19620
19621
19622 if (XMARKER (w->start)->buffer == current_buffer)
19623 compute_window_start_on_continuation_line (w);
19624
19625 w->window_end_valid = false;
19626
19627
19628 current_matrix_up_to_date_p = false;
19629 }
19630
19631
19632 CHECK_WINDOW_END (w);
19633 if (Z == Z_BYTE && CHARPOS (opoint) != BYTEPOS (opoint))
19634 emacs_abort ();
19635 if (BYTEPOS (opoint) < CHARPOS (opoint))
19636 emacs_abort ();
19637
19638 if (mode_line_update_needed (w))
19639 update_mode_line = true;
19640
19641
19642
19643 if (!EQ (window, selected_window))
19644 {
19645 ptrdiff_t new_pt = marker_position (w->pointm);
19646 ptrdiff_t new_pt_byte = marker_byte_position (w->pointm);
19647
19648 if (new_pt < BEGV)
19649 {
19650 new_pt = BEGV;
19651 new_pt_byte = BEGV_BYTE;
19652 set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
19653 }
19654 else if (new_pt > (ZV - 1))
19655 {
19656 new_pt = ZV;
19657 new_pt_byte = ZV_BYTE;
19658 set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
19659 }
19660
19661
19662 TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
19663 }
19664
19665
19666
19667
19668
19669
19670 if (current_buffer->width_run_cache
19671 || (current_buffer->base_buffer
19672 && current_buffer->base_buffer->width_run_cache))
19673 {
19674 struct Lisp_Char_Table *disptab = buffer_display_table ();
19675
19676 if (! disptab_matches_widthtab
19677 (disptab, XVECTOR (BVAR (current_buffer, width_table))))
19678 {
19679 struct buffer *buf = current_buffer;
19680
19681 if (buf->base_buffer)
19682 buf = buf->base_buffer;
19683 invalidate_region_cache (buf, buf->width_run_cache, BEG, Z);
19684 recompute_width_table (current_buffer, disptab);
19685 }
19686 }
19687
19688
19689 if (!NILP (Vlong_line_threshold)
19690 && !current_buffer->long_line_optimizations_p
19691 && (CHARS_MODIFF - UNCHANGED_MODIFIED > 8
19692 || current_buffer->clip_changed))
19693 {
19694 ptrdiff_t cur, next, found, max = 0, threshold;
19695 threshold = XFIXNUM (Vlong_line_threshold);
19696 for (cur = BEGV; cur < ZV; cur = next)
19697 {
19698 next = find_newline1 (cur, CHAR_TO_BYTE (cur), 0, -1, 1,
19699 &found, NULL, true);
19700 if (next - cur > max) max = next - cur;
19701 if (!found || max > threshold) break;
19702 }
19703 if (max > threshold)
19704 current_buffer->long_line_optimizations_p = true;
19705 }
19706
19707
19708 if (XMARKER (w->start)->buffer != current_buffer)
19709 goto recenter;
19710
19711 SET_TEXT_POS_FROM_MARKER (startp, w->start);
19712
19713
19714
19715 if ((w->optional_new_start || window_frozen_p (w))
19716 && CHARPOS (startp) >= BEGV
19717 && CHARPOS (startp) <= ZV)
19718 {
19719 ptrdiff_t it_charpos;
19720
19721 w->optional_new_start = false;
19722 if (!w->force_start)
19723 {
19724 start_display (&it, w, startp);
19725 move_it_to (&it, PT, 0, it.last_visible_y, -1,
19726 MOVE_TO_POS | MOVE_TO_X | MOVE_TO_Y);
19727
19728
19729 it_charpos = IT_CHARPOS (it);
19730
19731
19732
19733
19734
19735 if (it.current_y == 0 || line_bottom_y (&it) < it.last_visible_y)
19736 {
19737 if (it_charpos == PT)
19738 w->force_start = true;
19739
19740 else if (it_charpos > PT && CHARPOS (startp) <= PT)
19741 w->force_start = true;
19742 #ifdef GLYPH_DEBUG
19743 if (w->force_start)
19744 {
19745 if (window_frozen_p (w))
19746 debug_method_add (w, "set force_start from frozen window start");
19747 else
19748 debug_method_add (w, "set force_start from optional_new_start");
19749 }
19750 #endif
19751 }
19752 }
19753 }
19754
19755 force_start:
19756
19757
19758
19759 if (w->force_start)
19760 {
19761
19762 int new_vpos = -1;
19763
19764 w->force_start = false;
19765
19766
19767
19768
19769 if (!w->preserve_vscroll_p || !window_frozen_p (w))
19770 w->vscroll = 0;
19771
19772 w->preserve_vscroll_p = false;
19773 w->window_end_valid = false;
19774
19775
19776 if (!buffer_unchanged_p)
19777 w->base_line_number = 0;
19778
19779
19780
19781
19782
19783
19784
19785
19786 if (!update_mode_line
19787 || ! NILP (Vwindow_scroll_functions))
19788 {
19789 update_mode_line = true;
19790 w->update_mode_line = true;
19791 startp = run_window_scroll_functions (window, startp);
19792 }
19793
19794 if (CHARPOS (startp) < BEGV)
19795 SET_TEXT_POS (startp, BEGV, BEGV_BYTE);
19796 else if (CHARPOS (startp) > ZV)
19797 SET_TEXT_POS (startp, ZV, ZV_BYTE);
19798
19799
19800
19801 if (!window_start_acceptable_p (window, CHARPOS (startp)))
19802 goto ignore_start;
19803
19804
19805
19806
19807
19808
19809 clear_glyph_matrix (w->desired_matrix);
19810 if (!try_window (window, startp, 0))
19811 {
19812 w->force_start = true;
19813 clear_glyph_matrix (w->desired_matrix);
19814 goto need_larger_matrices;
19815 }
19816
19817 if (w->cursor.vpos < 0)
19818 {
19819
19820
19821
19822
19823
19824 struct glyph_row *r = NULL;
19825 Lisp_Object invprop =
19826 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
19827 Qnil, NULL);
19828
19829 if (TEXT_PROP_MEANS_INVISIBLE (invprop) != 0)
19830 {
19831 ptrdiff_t alt_pt;
19832 Lisp_Object invprop_end =
19833 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
19834 Qnil, Qnil);
19835
19836 if (FIXNATP (invprop_end))
19837 alt_pt = XFIXNAT (invprop_end);
19838 else
19839 alt_pt = ZV;
19840 r = row_containing_pos (w, alt_pt, w->desired_matrix->rows,
19841 NULL, 0);
19842 }
19843 if (r)
19844 new_vpos = MATRIX_ROW_BOTTOM_Y (r);
19845 else
19846 new_vpos = window_box_height (w) / 2;
19847 }
19848
19849 if (!cursor_row_fully_visible_p (w, false, false, false))
19850 {
19851
19852
19853 new_vpos = window_box_height (w);
19854
19855
19856
19857
19858
19859
19860 if (new_vpos >= w->cursor.y)
19861 {
19862 w->cursor.vpos = -1;
19863 clear_glyph_matrix (w->desired_matrix);
19864 goto try_to_scroll;
19865 }
19866 }
19867 else if (w->cursor.vpos >= 0)
19868 {
19869
19870
19871
19872 int pixel_margin = margin * frame_line_height;
19873 bool tab_line = window_wants_tab_line (w);
19874 bool header_line = window_wants_header_line (w);
19875
19876
19877
19878
19879
19880 if (w->cursor.vpos < margin + tab_line + header_line)
19881 {
19882 w->cursor.vpos = -1;
19883 clear_glyph_matrix (w->desired_matrix);
19884 goto try_to_scroll;
19885 }
19886 else
19887 {
19888 int window_height = window_box_height (w);
19889
19890 if (tab_line)
19891 window_height += CURRENT_TAB_LINE_HEIGHT (w);
19892 if (header_line)
19893 window_height += CURRENT_HEADER_LINE_HEIGHT (w);
19894 if (w->cursor.y >= window_height - pixel_margin)
19895 {
19896 w->cursor.vpos = -1;
19897 clear_glyph_matrix (w->desired_matrix);
19898 goto try_to_scroll;
19899 }
19900 }
19901 }
19902
19903
19904
19905 if (new_vpos >= 0)
19906 {
19907 struct glyph_row *row;
19908
19909 row = MATRIX_FIRST_TEXT_ROW (w->desired_matrix);
19910 while (MATRIX_ROW_BOTTOM_Y (row) < new_vpos
19911 && !row->ends_at_zv_p)
19912 ++row;
19913
19914 TEMP_SET_PT_BOTH (MATRIX_ROW_START_CHARPOS (row),
19915 MATRIX_ROW_START_BYTEPOS (row));
19916
19917 if (w != XWINDOW (selected_window))
19918 set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
19919 else if (current_buffer == old)
19920 SET_TEXT_POS (lpoint, PT, PT_BYTE);
19921
19922 set_cursor_from_row (w, row, w->desired_matrix, 0, 0, 0, 0);
19923
19924
19925
19926
19927
19928
19929
19930 w->redisplay = false;
19931 XBUFFER (w->contents)->text->redisplay = false;
19932 safe__call1 (true, Vpre_redisplay_function, Fcons (window, Qnil));
19933
19934 if (w->redisplay || XBUFFER (w->contents)->text->redisplay
19935 || ((EQ (Vdisplay_line_numbers, Qrelative)
19936 || EQ (Vdisplay_line_numbers, Qvisual))
19937 && row != MATRIX_FIRST_TEXT_ROW (w->desired_matrix)))
19938 {
19939
19940
19941
19942
19943 clear_glyph_matrix (w->desired_matrix);
19944 if (!try_window (window, startp, 0))
19945 goto need_larger_matrices;
19946 }
19947 }
19948 if (w->cursor.vpos < 0
19949 || !cursor_row_fully_visible_p (w, false, false, false))
19950 {
19951 clear_glyph_matrix (w->desired_matrix);
19952 goto try_to_scroll;
19953 }
19954
19955 #ifdef GLYPH_DEBUG
19956 debug_method_add (w, "forced window start");
19957 #endif
19958 goto done;
19959 }
19960
19961 ignore_start:
19962
19963
19964
19965
19966 if (current_matrix_up_to_date_p
19967 && (rc = try_cursor_movement (window, startp, &temp_scroll_step),
19968 rc != CURSOR_MOVEMENT_CANNOT_BE_USED))
19969 {
19970 switch (rc)
19971 {
19972 case CURSOR_MOVEMENT_SUCCESS:
19973 used_current_matrix_p = true;
19974 goto done;
19975
19976 case CURSOR_MOVEMENT_MUST_SCROLL:
19977 goto try_to_scroll;
19978
19979 default:
19980 emacs_abort ();
19981 }
19982 }
19983
19984
19985
19986 else if (w->start_at_line_beg
19987 && ((CHARPOS (startp) > BEGV
19988 && FETCH_BYTE (BYTEPOS (startp) - 1) != '\n')
19989 || (CHARPOS (startp) >= BEGV
19990 && CHARPOS (startp) <= ZV
19991 && !window_start_acceptable_p (window, CHARPOS (startp)))))
19992 {
19993 #ifdef GLYPH_DEBUG
19994 debug_method_add (w, "recenter 1");
19995 #endif
19996 goto recenter;
19997 }
19998
19999
20000
20001
20002 else if ((tem = try_window_id (w)) != 0)
20003 {
20004 #ifdef GLYPH_DEBUG
20005 debug_method_add (w, "try_window_id %d", tem);
20006 #endif
20007
20008 if (f->fonts_changed)
20009 goto need_larger_matrices;
20010 if (tem > 0)
20011 goto done;
20012
20013
20014
20015 }
20016 else if (CHARPOS (startp) >= BEGV
20017 && CHARPOS (startp) <= ZV
20018 && PT >= CHARPOS (startp)
20019 && (CHARPOS (startp) < ZV
20020
20021 || CHARPOS (startp) == BEGV
20022 || !window_outdated (w)))
20023 {
20024 int d1, d2, d5, d6;
20025 int rtop, rbot;
20026
20027
20028
20029
20030
20031
20032
20033
20034
20035
20036 if (!w->start_at_line_beg
20037 && NILP (track_mouse)
20038 && CHARPOS (startp) > BEGV
20039 && CHARPOS (startp) > BEG + beg_unchanged
20040 && CHARPOS (startp) <= Z - end_unchanged
20041
20042
20043
20044
20045
20046 && XMARKER (w->start)->buffer == current_buffer
20047 && compute_window_start_on_continuation_line (w)
20048
20049
20050
20051
20052
20053
20054 && pos_visible_p (w, PT, &d1, &d2, &rtop, &rbot, &d5, &d6)
20055
20056
20057 && (rtop != 0) == (rbot != 0))
20058 {
20059 w->force_start = true;
20060 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20061 #ifdef GLYPH_DEBUG
20062 debug_method_add (w, "recomputed window start in continuation line");
20063 #endif
20064 goto force_start;
20065 }
20066
20067
20068
20069
20070 if (!window_start_acceptable_p (window, CHARPOS (startp)))
20071 {
20072 #ifdef GLYPH_DEBUG
20073 debug_method_add (w, "recenter 2");
20074 #endif
20075 goto recenter;
20076 }
20077
20078 #ifdef GLYPH_DEBUG
20079 debug_method_add (w, "same window start");
20080 #endif
20081
20082
20083
20084 if (!current_matrix_up_to_date_p
20085
20086
20087
20088 || !NILP (Vwindow_scroll_functions)
20089 || MINI_WINDOW_P (w)
20090 || !(used_current_matrix_p
20091 = try_window_reusing_current_matrix (w)))
20092 {
20093 IF_DEBUG (debug_method_add (w, "1"));
20094 clear_glyph_matrix (w->desired_matrix);
20095 if (try_window (window, startp, TRY_WINDOW_CHECK_MARGINS) < 0)
20096
20097
20098
20099 goto try_to_scroll;
20100 }
20101
20102 if (f->fonts_changed)
20103 goto need_larger_matrices;
20104
20105 if (w->cursor.vpos >= 0)
20106 {
20107 if (!just_this_one_p
20108 || current_buffer->clip_changed
20109 || BEG_UNCHANGED < CHARPOS (startp))
20110
20111 w->base_line_number = 0;
20112
20113 if (!cursor_row_fully_visible_p (w, true, false, false))
20114 {
20115 clear_glyph_matrix (w->desired_matrix);
20116 last_line_misfit = true;
20117 }
20118
20119 else
20120 goto done;
20121 }
20122 else
20123 clear_glyph_matrix (w->desired_matrix);
20124 }
20125
20126 try_to_scroll:
20127
20128
20129 if (!update_mode_line)
20130 {
20131 update_mode_line = true;
20132 w->update_mode_line = true;
20133 }
20134
20135
20136 if ((0 < scroll_conservatively
20137
20138
20139
20140
20141 || (scroll_minibuffer_conservatively && MINI_WINDOW_P (w))
20142 || 0 < emacs_scroll_step
20143 || temp_scroll_step
20144 || NUMBERP (BVAR (current_buffer, scroll_up_aggressively))
20145 || NUMBERP (BVAR (current_buffer, scroll_down_aggressively)))
20146 && CHARPOS (startp) >= BEGV
20147 && CHARPOS (startp) <= ZV)
20148 {
20149
20150
20151 int ss = try_scrolling (window, just_this_one_p,
20152 ((scroll_minibuffer_conservatively
20153 && MINI_WINDOW_P (w))
20154 ? SCROLL_LIMIT + 1
20155 : scroll_conservatively),
20156 emacs_scroll_step,
20157 temp_scroll_step, last_line_misfit);
20158 switch (ss)
20159 {
20160 case SCROLLING_SUCCESS:
20161 goto done;
20162
20163 case SCROLLING_NEED_LARGER_MATRICES:
20164 goto need_larger_matrices;
20165
20166 case SCROLLING_FAILED:
20167 break;
20168
20169 default:
20170 emacs_abort ();
20171 }
20172 }
20173
20174
20175
20176
20177 recenter:
20178
20179 #ifdef GLYPH_DEBUG
20180 debug_method_add (w, "recenter");
20181 #endif
20182
20183
20184 if (!buffer_unchanged_p)
20185 w->base_line_number = 0;
20186
20187
20188 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20189 it.current_y = it.last_visible_y;
20190 if (centering_position < 0)
20191 {
20192 ptrdiff_t margin_pos = CHARPOS (startp);
20193 Lisp_Object aggressive;
20194 bool scrolling_up;
20195
20196
20197
20198 if (margin
20199
20200
20201
20202
20203
20204
20205 && BEGV <= CHARPOS (startp) && CHARPOS (startp) <= ZV)
20206 {
20207 struct it it1;
20208 void *it1data = NULL;
20209
20210 SAVE_IT (it1, it, it1data);
20211 start_display (&it1, w, startp);
20212 move_it_vertically (&it1, margin * frame_line_height);
20213 margin_pos = IT_CHARPOS (it1);
20214 RESTORE_IT (&it, &it, it1data);
20215 }
20216 scrolling_up = PT > margin_pos;
20217 aggressive =
20218 scrolling_up
20219 ? BVAR (current_buffer, scroll_up_aggressively)
20220 : BVAR (current_buffer, scroll_down_aggressively);
20221
20222 if (!MINI_WINDOW_P (w)
20223 && (scroll_conservatively > SCROLL_LIMIT || NUMBERP (aggressive)))
20224 {
20225 int pt_offset = 0;
20226
20227
20228
20229 if (!scroll_conservatively && NUMBERP (aggressive))
20230 {
20231 double float_amount = XFLOATINT (aggressive);
20232
20233 pt_offset = float_amount * WINDOW_BOX_TEXT_HEIGHT (w);
20234 if (pt_offset == 0 && float_amount > 0)
20235 pt_offset = 1;
20236 if (pt_offset && margin > 0)
20237 margin -= 1;
20238 }
20239
20240
20241
20242 if (scrolling_up)
20243 {
20244 centering_position = it.last_visible_y;
20245 if (pt_offset)
20246 centering_position -= pt_offset;
20247 centering_position -=
20248 (frame_line_height * (1 + margin + last_line_misfit)
20249 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
20250
20251
20252 if (centering_position < margin * frame_line_height)
20253 centering_position = margin * frame_line_height;
20254 }
20255 else
20256 centering_position = margin * frame_line_height + pt_offset;
20257 }
20258 else
20259
20260
20261 centering_position = window_box_height (w) / 2;
20262 }
20263 if (current_buffer->long_line_optimizations_p
20264 && it.line_wrap == TRUNCATE)
20265 {
20266
20267
20268
20269 int nlines = centering_position / frame_line_height;
20270
20271 while (nlines-- && IT_CHARPOS (it) > BEGV)
20272 back_to_previous_visible_line_start (&it);
20273 reseat_1 (&it, it.current.pos, true);
20274 }
20275 else
20276 move_it_vertically_backward (&it, centering_position);
20277
20278 eassert (IT_CHARPOS (it) >= BEGV);
20279
20280
20281
20282
20283
20284
20285 if (it.current_y <= 0)
20286 {
20287 init_iterator (&it, w, PT, PT_BYTE, NULL, DEFAULT_FACE_ID);
20288 move_it_vertically_backward (&it, 0);
20289 it.current_y = 0;
20290 }
20291
20292 it.current_x = it.hpos = 0;
20293
20294
20295
20296
20297 set_marker_both (w->start, Qnil, IT_CHARPOS (it), IT_BYTEPOS (it));
20298
20299
20300 startp = run_window_scroll_functions (window, it.current.pos);
20301
20302
20303
20304
20305 itdata = bidi_shelve_cache ();
20306
20307
20308 use_desired_matrix = false;
20309 if (!current_matrix_up_to_date_p
20310 || windows_or_buffers_changed
20311 || f->cursor_type_changed
20312
20313
20314 || !NILP (Vwindow_scroll_functions)
20315 || !just_this_one_p
20316 || MINI_WINDOW_P (w)
20317 || !(used_current_matrix_p
20318 = try_window_reusing_current_matrix (w)))
20319 use_desired_matrix = (try_window (window, startp, 0) == 1);
20320
20321 bidi_unshelve_cache (itdata, false);
20322
20323
20324
20325
20326 if (f->fonts_changed)
20327 goto need_larger_matrices;
20328
20329
20330
20331
20332
20333
20334 if (w->cursor.vpos < 0)
20335 {
20336 if (w->window_end_valid && PT >= Z - w->window_end_pos)
20337 {
20338 clear_glyph_matrix (w->desired_matrix);
20339 move_it_by_lines (&it, 1);
20340 try_window (window, it.current.pos, 0);
20341 }
20342 else if (PT < IT_CHARPOS (it))
20343 {
20344 clear_glyph_matrix (w->desired_matrix);
20345 move_it_by_lines (&it, -1);
20346 try_window (window, it.current.pos, 0);
20347 }
20348 else if (scroll_conservatively > SCROLL_LIMIT
20349 && (it.method == GET_FROM_STRING
20350 || overlay_touches_p (IT_CHARPOS (it)))
20351 && IT_CHARPOS (it) < ZV)
20352 {
20353
20354
20355
20356
20357
20358
20359
20360
20361 ptrdiff_t pos0 = IT_CHARPOS (it);
20362
20363 clear_glyph_matrix (w->desired_matrix);
20364 do {
20365 move_it_by_lines (&it, 1);
20366 } while (IT_CHARPOS (it) == pos0);
20367 try_window (window, it.current.pos, 0);
20368 }
20369 else
20370 {
20371
20372 }
20373 }
20374
20375
20376
20377
20378
20379
20380 if (w->cursor.vpos < 0)
20381 {
20382
20383
20384
20385
20386 struct glyph_matrix *matrix =
20387 use_desired_matrix ? w->desired_matrix : w->current_matrix;
20388
20389 struct glyph_row *row =
20390 row_containing_pos (w, PT, matrix->rows, NULL, 0);
20391
20392
20393
20394
20395
20396
20397
20398 if (!row)
20399 {
20400 Lisp_Object val =
20401 get_char_property_and_overlay (make_fixnum (PT), Qinvisible,
20402 Qnil, NULL);
20403
20404 if (TEXT_PROP_MEANS_INVISIBLE (val) != 0)
20405 {
20406 ptrdiff_t alt_pos;
20407 Lisp_Object invis_end =
20408 Fnext_single_char_property_change (make_fixnum (PT), Qinvisible,
20409 Qnil, Qnil);
20410
20411 if (FIXNATP (invis_end))
20412 alt_pos = XFIXNAT (invis_end);
20413 else
20414 alt_pos = ZV;
20415 row = row_containing_pos (w, alt_pos, matrix->rows, NULL, 0);
20416 }
20417 }
20418
20419
20420
20421 if (!row)
20422 {
20423 row = matrix->rows;
20424
20425 if (row->tab_line_p)
20426 ++row;
20427 if (row->mode_line_p)
20428 ++row;
20429 }
20430 set_cursor_from_row (w, row, matrix, 0, 0, 0, 0);
20431 }
20432
20433 if (!cursor_row_fully_visible_p (w, false, false, false))
20434 {
20435
20436 if (w->vscroll)
20437 {
20438 w->vscroll = 0;
20439 clear_glyph_matrix (w->desired_matrix);
20440 goto recenter;
20441 }
20442
20443
20444
20445
20446
20447 if (scroll_conservatively > SCROLL_LIMIT)
20448 {
20449 int window_total_lines
20450 = WINDOW_TOTAL_LINES (w) * FRAME_LINE_HEIGHT (f) / frame_line_height;
20451 bool move_down = w->cursor.vpos >= window_total_lines / 2;
20452
20453 move_it_by_lines (&it, move_down ? margin + 1 : -(margin + 1));
20454 clear_glyph_matrix (w->desired_matrix);
20455 if (1 == try_window (window, it.current.pos,
20456 TRY_WINDOW_CHECK_MARGINS))
20457 goto done;
20458 }
20459
20460
20461
20462
20463 if (centering_position == 0)
20464 goto done;
20465
20466 clear_glyph_matrix (w->desired_matrix);
20467 centering_position = 0;
20468 goto recenter;
20469 }
20470
20471 done:
20472
20473 SET_TEXT_POS_FROM_MARKER (startp, w->start);
20474 w->start_at_line_beg = (CHARPOS (startp) == BEGV
20475 || FETCH_BYTE (BYTEPOS (startp) - 1) == '\n');
20476
20477
20478 if ((update_mode_line
20479
20480
20481
20482
20483 || (!just_this_one_p
20484 && !FRAME_WINDOW_P (f)
20485 && !WINDOW_FULL_WIDTH_P (w))
20486
20487 || w->base_line_pos > 0
20488
20489 || (w->column_number_displayed != -1
20490 && (w->column_number_displayed != current_column ())))
20491
20492 && (window_wants_mode_line (w)
20493 || window_wants_header_line (w)
20494 || window_wants_tab_line (w)))
20495 {
20496 specpdl_ref count1 = SPECPDL_INDEX ();
20497
20498 specbind (Qinhibit_quit, Qt);
20499 display_mode_lines (w);
20500 unbind_to (count1, Qnil);
20501
20502
20503
20504 if (window_wants_mode_line (w)
20505 && CURRENT_MODE_LINE_HEIGHT (w) != DESIRED_MODE_LINE_HEIGHT (w))
20506 {
20507 f->fonts_changed = true;
20508 w->mode_line_height = -1;
20509 MATRIX_MODE_LINE_ROW (w->current_matrix)->height
20510 = DESIRED_MODE_LINE_HEIGHT (w);
20511 }
20512
20513
20514
20515 if (window_wants_tab_line (w)
20516 && CURRENT_TAB_LINE_HEIGHT (w) != DESIRED_TAB_LINE_HEIGHT (w))
20517 {
20518 f->fonts_changed = true;
20519 w->tab_line_height = -1;
20520 MATRIX_TAB_LINE_ROW (w->current_matrix)->height
20521 = DESIRED_TAB_LINE_HEIGHT (w);
20522 }
20523
20524
20525
20526 if (window_wants_header_line (w)
20527 && CURRENT_HEADER_LINE_HEIGHT (w) != DESIRED_HEADER_LINE_HEIGHT (w))
20528 {
20529 f->fonts_changed = true;
20530 w->header_line_height = -1;
20531 MATRIX_HEADER_LINE_ROW (w->current_matrix)->height
20532 = DESIRED_HEADER_LINE_HEIGHT (w);
20533 }
20534
20535 if (f->fonts_changed)
20536 goto need_larger_matrices;
20537 }
20538
20539 if (!line_number_displayed && w->base_line_pos != -1)
20540 {
20541 w->base_line_pos = 0;
20542 w->base_line_number = 0;
20543 }
20544
20545 finish_menu_bars:
20546
20547
20548
20549 if (update_mode_line
20550 && EQ (FRAME_SELECTED_WINDOW (f), window))
20551 {
20552 bool redisplay_menu_p;
20553
20554 if (FRAME_WINDOW_P (f))
20555 {
20556 #ifdef HAVE_EXT_MENU_BAR
20557 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
20558 #else
20559 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20560 #endif
20561 }
20562 else
20563 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
20564
20565 if (redisplay_menu_p)
20566 display_menu_bar (w);
20567
20568 #ifdef HAVE_WINDOW_SYSTEM
20569 if (FRAME_WINDOW_P (f))
20570 {
20571 if (WINDOWP (f->tab_bar_window)
20572 && (FRAME_TAB_BAR_LINES (f) > 0
20573 || !NILP (Vauto_resize_tab_bars))
20574 && redisplay_tab_bar (f))
20575 ignore_mouse_drag_p = true;
20576
20577 #ifdef HAVE_EXT_TOOL_BAR
20578 if (FRAME_EXTERNAL_TOOL_BAR (f))
20579 update_frame_tool_bar (f);
20580 #else
20581 if (WINDOWP (f->tool_bar_window)
20582 && (FRAME_TOOL_BAR_LINES (f) > 0
20583 || !NILP (Vauto_resize_tool_bars))
20584 && redisplay_tool_bar (f))
20585 ignore_mouse_drag_p = true;
20586 #endif
20587 }
20588 else
20589 {
20590 if ((FRAME_TAB_BAR_LINES (f) > 0))
20591 display_tab_bar (w);
20592 }
20593
20594 gui_consider_frame_title (w->frame);
20595 #else
20596 if ((FRAME_TAB_BAR_LINES (f) > 0))
20597 display_tab_bar (w);
20598 #endif
20599 }
20600
20601 #ifdef HAVE_WINDOW_SYSTEM
20602 if (FRAME_WINDOW_P (f)
20603 && update_window_fringes (w, (just_this_one_p
20604 || (!used_current_matrix_p && !overlay_arrow_seen)
20605 || w->pseudo_window_p)))
20606 {
20607 update_begin (f);
20608 block_input ();
20609 if (draw_window_fringes (w, true))
20610 {
20611 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
20612 gui_draw_right_divider (w);
20613 else
20614 gui_draw_vertical_border (w);
20615 }
20616 unblock_input ();
20617 update_end (f);
20618 }
20619
20620 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
20621 gui_draw_bottom_divider (w);
20622 #endif
20623
20624
20625
20626
20627
20628 need_larger_matrices:
20629 ;
20630 finish_scroll_bars:
20631
20632 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w) || WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20633 {
20634 if (WINDOW_HAS_VERTICAL_SCROLL_BAR (w))
20635
20636 set_vertical_scroll_bar (w);
20637
20638 if (WINDOW_HAS_HORIZONTAL_SCROLL_BAR (w))
20639
20640 set_horizontal_scroll_bar (w);
20641
20642
20643
20644 if (FRAME_TERMINAL (f)->redeem_scroll_bar_hook)
20645 (*FRAME_TERMINAL (f)->redeem_scroll_bar_hook) (w);
20646 }
20647
20648
20649
20650
20651 if (CHARPOS (opoint) < BEGV)
20652 TEMP_SET_PT_BOTH (BEGV, BEGV_BYTE);
20653 else if (CHARPOS (opoint) > ZV)
20654 TEMP_SET_PT_BOTH (Z, Z_BYTE);
20655 else
20656 TEMP_SET_PT_BOTH (CHARPOS (opoint), BYTEPOS (opoint));
20657
20658 set_buffer_internal_1 (old);
20659
20660
20661 if (CHARPOS (lpoint) <= ZV)
20662 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
20663
20664 unbind_to (count, Qnil);
20665 }
20666
20667
20668
20669
20670
20671
20672
20673
20674
20675
20676
20677
20678
20679
20680
20681
20682
20683
20684
20685
20686 int
20687 try_window (Lisp_Object window, struct text_pos pos, int flags)
20688 {
20689 struct window *w = XWINDOW (window);
20690 struct it it;
20691 struct glyph_row *last_text_row = NULL;
20692 struct frame *f = XFRAME (w->frame);
20693 int cursor_vpos = w->cursor.vpos;
20694
20695
20696 set_marker_both (w->start, Qnil, CHARPOS (pos), BYTEPOS (pos));
20697
20698
20699 w->cursor.vpos = -1;
20700 overlay_arrow_seen = false;
20701
20702
20703 start_display (&it, w, pos);
20704 it.glyph_row->reversed_p = false;
20705
20706
20707 while (it.current_y < it.last_visible_y)
20708 {
20709 int last_row_scale = it.w->nrows_scale_factor;
20710 int last_col_scale = it.w->ncols_scale_factor;
20711 if (display_line (&it, cursor_vpos))
20712 last_text_row = it.glyph_row - 1;
20713 if (f->fonts_changed
20714 && !((flags & TRY_WINDOW_IGNORE_FONTS_CHANGE)
20715
20716
20717 && last_row_scale == it.w->nrows_scale_factor
20718 && last_col_scale == it.w->ncols_scale_factor))
20719 return 0;
20720 }
20721
20722
20723
20724 ptrdiff_t it_charpos = IT_CHARPOS (it);
20725
20726
20727
20728
20729 if ((flags & TRY_WINDOW_CHECK_MARGINS)
20730 && w->vscroll == 0
20731 && !MINI_WINDOW_P (w))
20732 {
20733 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
20734 int bot_scroll_margin = top_scroll_margin;
20735 if (window_wants_header_line (w))
20736 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
20737 if (window_wants_tab_line (w))
20738 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
20739 start_display (&it, w, pos);
20740
20741 if ((w->cursor.y >= 0
20742 && w->cursor.y < top_scroll_margin
20743 && CHARPOS (pos) > BEGV)
20744
20745
20746
20747
20748 || w->cursor.y > (it.last_visible_y - partial_line_height (&it)
20749 - bot_scroll_margin - 1))
20750 {
20751 w->cursor.vpos = -1;
20752 clear_glyph_matrix (w->desired_matrix);
20753 return -1;
20754 }
20755 }
20756
20757
20758 if (w->window_end_pos <= 0 && Z != it_charpos)
20759 w->update_mode_line = true;
20760
20761
20762
20763
20764 if (last_text_row)
20765 {
20766 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_text_row));
20767 adjust_window_ends (w, last_text_row, false);
20768 eassert
20769 (MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->desired_matrix,
20770 w->window_end_vpos)));
20771 }
20772 else
20773 {
20774 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
20775 w->window_end_pos = Z - ZV;
20776 w->window_end_vpos = 0;
20777 }
20778
20779
20780 w->window_end_valid = false;
20781 return 1;
20782 }
20783
20784
20785
20786
20787
20788
20789
20790
20791
20792
20793
20794
20795 static bool
20796 try_window_reusing_current_matrix (struct window *w)
20797 {
20798 struct frame *f = XFRAME (w->frame);
20799 struct glyph_row *bottom_row;
20800 struct it it;
20801 struct run run;
20802 struct text_pos start, new_start;
20803 int nrows_scrolled, i;
20804 struct glyph_row *last_text_row;
20805 struct glyph_row *last_reused_text_row;
20806 struct glyph_row *start_row;
20807 int start_vpos, min_y, max_y;
20808
20809 #ifdef GLYPH_DEBUG
20810 if (inhibit_try_window_reusing)
20811 return false;
20812 #endif
20813
20814 if (
20815 !FRAME_WINDOW_P (f)
20816
20817
20818 || windows_or_buffers_changed
20819 || f->cursor_type_changed
20820
20821
20822
20823 || overlay_arrow_in_current_buffer_p ())
20824 return false;
20825
20826
20827 if (!NILP (Vshow_trailing_whitespace))
20828 return false;
20829
20830
20831 if (window_wants_tab_line (w)
20832 != MATRIX_TAB_LINE_ROW (w->current_matrix)->mode_line_p)
20833 return false;
20834
20835
20836 if (window_wants_header_line (w)
20837 != MATRIX_HEADER_LINE_ROW (w->current_matrix)->mode_line_p)
20838 return false;
20839
20840
20841
20842 start_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20843 if (w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row))
20844 return false;
20845
20846
20847 clear_glyph_matrix (w->desired_matrix);
20848
20849
20850
20851
20852 if (!NILP (Vdisplay_line_numbers))
20853 return false;
20854
20855
20856
20857
20858 #ifdef HAVE_NTGUI
20859 if (w32_use_visible_system_caret)
20860 return false;
20861 #endif
20862
20863
20864
20865 SET_TEXT_POS_FROM_MARKER (new_start, w->start);
20866 start = start_row->minpos;
20867 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
20868
20869 if (CHARPOS (new_start) <= CHARPOS (start))
20870 {
20871
20872
20873
20874
20875 if (in_ellipses_for_invisible_text_p (&start_row->start, w))
20876 return false;
20877
20878 IF_DEBUG (debug_method_add (w, "twu1"));
20879
20880
20881
20882
20883
20884 start_display (&it, w, new_start);
20885 w->cursor.vpos = -1;
20886 last_text_row = last_reused_text_row = NULL;
20887
20888 while (it.current_y < it.last_visible_y && !f->fonts_changed)
20889 {
20890
20891
20892
20893
20894 while (IT_CHARPOS (it) > CHARPOS (start))
20895 {
20896
20897 start_row++;
20898 start = start_row->minpos;
20899
20900 if (start_row == MATRIX_MODE_LINE_ROW (w->current_matrix) - 1
20901 || w->vscroll || MATRIX_ROW_PARTIALLY_VISIBLE_P (w, start_row)
20902 || CHARPOS (start) == ZV)
20903 {
20904 clear_glyph_matrix (w->desired_matrix);
20905 return false;
20906 }
20907
20908 start_vpos = MATRIX_ROW_VPOS (start_row, w->current_matrix);
20909 }
20910
20911
20912 if (IT_CHARPOS (it) == CHARPOS (start)
20913
20914
20915
20916
20917
20918 && it.current.dpvec_index < 0)
20919 break;
20920
20921 it.glyph_row->reversed_p = false;
20922 if (display_line (&it, -1))
20923 last_text_row = it.glyph_row - 1;
20924
20925 }
20926
20927
20928
20929
20930 if (it.current_y < it.last_visible_y)
20931 {
20932 struct glyph_row *row;
20933
20934
20935 nrows_scrolled = it.vpos - (start_row - MATRIX_FIRST_TEXT_ROW (w->current_matrix));
20936
20937
20938 if (w->cursor.vpos < 0)
20939 {
20940 int dy = it.current_y - start_row->y;
20941
20942 row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
20943 row = row_containing_pos (w, PT, row, NULL, dy);
20944 if (row)
20945 set_cursor_from_row (w, row, w->current_matrix, 0, 0,
20946 dy, nrows_scrolled);
20947 else
20948 {
20949 clear_glyph_matrix (w->desired_matrix);
20950 return false;
20951 }
20952 }
20953
20954
20955
20956
20957
20958
20959
20960 run.current_y = start_row->y;
20961 run.desired_y = it.current_y;
20962 run.height = it.last_visible_y - it.current_y;
20963
20964 if (run.height > 0 && run.current_y != run.desired_y)
20965 {
20966 #ifdef HAVE_WINDOW_SYSTEM
20967 update_begin (f);
20968 gui_update_window_begin (w);
20969 FRAME_RIF (f)->clear_window_mouse_face (w);
20970 FRAME_RIF (f)->scroll_run_hook (w, &run);
20971 gui_update_window_end (w, false, false);
20972 update_end (f);
20973 #endif
20974 }
20975
20976
20977 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
20978 rotate_matrix (w->current_matrix,
20979 start_vpos,
20980 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
20981 nrows_scrolled);
20982
20983
20984 for (i = 0; i < nrows_scrolled; ++i)
20985 (start_row + i)->enabled_p = false;
20986
20987
20988 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
20989 max_y = it.last_visible_y;
20990 for (row = start_row + nrows_scrolled;
20991 row < bottom_row;
20992 ++row)
20993 {
20994 row->y = it.current_y;
20995 row->visible_height = row->height;
20996
20997 if (row->y < min_y)
20998 row->visible_height -= min_y - row->y;
20999 if (row->y + row->height > max_y)
21000 row->visible_height -= row->y + row->height - max_y;
21001 if (row->fringe_bitmap_periodic_p)
21002 row->redraw_fringe_bitmaps_p = true;
21003
21004 it.current_y += row->height;
21005
21006 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21007 last_reused_text_row = row;
21008 if (MATRIX_ROW_BOTTOM_Y (row) >= it.last_visible_y)
21009 break;
21010 }
21011
21012
21013
21014 for (++row; row < bottom_row; ++row)
21015 row->enabled_p = row->mode_line_p = row->tab_line_p = false;
21016 }
21017
21018
21019
21020
21021
21022 if (last_reused_text_row)
21023 adjust_window_ends (w, last_reused_text_row, true);
21024 else if (last_text_row)
21025 adjust_window_ends (w, last_text_row, false);
21026 else
21027 {
21028
21029 w->window_end_bytepos = Z_BYTE - ZV_BYTE;
21030 w->window_end_pos = Z - ZV;
21031 w->window_end_vpos = 0;
21032 }
21033 w->window_end_valid = false;
21034
21035
21036 w->desired_matrix->no_scrolling_p = true;
21037
21038 #ifdef GLYPH_DEBUG
21039 debug_method_add (w, "try_window_reusing_current_matrix 1");
21040 #endif
21041 return true;
21042 }
21043 else if (CHARPOS (new_start) > CHARPOS (start))
21044 {
21045 struct glyph_row *pt_row, *row;
21046 struct glyph_row *first_reusable_row;
21047 struct glyph_row *first_row_to_display;
21048 int dy;
21049 int yb = window_text_bottom_y (w);
21050
21051
21052
21053 first_reusable_row = start_row;
21054 while (first_reusable_row->enabled_p
21055 && MATRIX_ROW_BOTTOM_Y (first_reusable_row) < yb
21056 && (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21057 < CHARPOS (new_start)))
21058 ++first_reusable_row;
21059
21060
21061 if (MATRIX_ROW_BOTTOM_Y (first_reusable_row) >= yb
21062 || !first_reusable_row->enabled_p
21063 || (MATRIX_ROW_START_CHARPOS (first_reusable_row)
21064 != CHARPOS (new_start)))
21065 return false;
21066
21067
21068
21069
21070
21071 pt_row = NULL;
21072 for (first_row_to_display = first_reusable_row;
21073 MATRIX_ROW_BOTTOM_Y (first_row_to_display) < yb;
21074 ++first_row_to_display)
21075 {
21076 if (PT >= MATRIX_ROW_START_CHARPOS (first_row_to_display)
21077 && (PT < MATRIX_ROW_END_CHARPOS (first_row_to_display)
21078 || (PT == MATRIX_ROW_END_CHARPOS (first_row_to_display)
21079 && first_row_to_display->ends_at_zv_p
21080 && pt_row == NULL)))
21081 pt_row = first_row_to_display;
21082 }
21083
21084 if (first_row_to_display->y >= yb)
21085 return false;
21086
21087
21088 init_to_row_start (&it, w, first_row_to_display);
21089
21090 nrows_scrolled = (MATRIX_ROW_VPOS (first_reusable_row, w->current_matrix)
21091 - start_vpos);
21092 it.vpos = (MATRIX_ROW_VPOS (first_row_to_display, w->current_matrix)
21093 - nrows_scrolled);
21094 it.current_y = (first_row_to_display->y - first_reusable_row->y
21095 + WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w));
21096
21097
21098
21099
21100 it.glyph_row = MATRIX_ROW (w->desired_matrix, it.vpos);
21101 if (pt_row == NULL)
21102 w->cursor.vpos = -1;
21103 last_text_row = NULL;
21104 while (it.current_y < it.last_visible_y && !f->fonts_changed)
21105 if (display_line (&it, w->cursor.vpos))
21106 last_text_row = it.glyph_row - 1;
21107
21108
21109
21110 if (pt_row)
21111 {
21112 w->cursor.vpos -= nrows_scrolled;
21113 w->cursor.y -= first_reusable_row->y - start_row->y;
21114 }
21115
21116
21117
21118
21119
21120 if (w->cursor.vpos < 0)
21121 {
21122 clear_glyph_matrix (w->desired_matrix);
21123 return false;
21124 }
21125
21126
21127 run.current_y = first_reusable_row->y;
21128 run.desired_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21129 run.height = it.last_visible_y - run.current_y;
21130 dy = run.current_y - run.desired_y;
21131
21132 if (run.height)
21133 {
21134 #ifdef HAVE_WINDOW_SYSTEM
21135 update_begin (f);
21136 gui_update_window_begin (w);
21137 FRAME_RIF (f)->clear_window_mouse_face (w);
21138 FRAME_RIF (f)->scroll_run_hook (w, &run);
21139 gui_update_window_end (w, false, false);
21140 update_end (f);
21141 #endif
21142 }
21143
21144
21145 bottom_row = MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w);
21146 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
21147 max_y = it.last_visible_y;
21148 for (row = first_reusable_row; row < first_row_to_display; ++row)
21149 {
21150 row->y -= dy;
21151 row->visible_height = row->height;
21152 if (row->y < min_y)
21153 row->visible_height -= min_y - row->y;
21154 if (row->y + row->height > max_y)
21155 row->visible_height -= row->y + row->height - max_y;
21156 if (row->fringe_bitmap_periodic_p)
21157 row->redraw_fringe_bitmaps_p = true;
21158 }
21159
21160
21161 eassert (nrows_scrolled > 0);
21162 rotate_matrix (w->current_matrix,
21163 start_vpos,
21164 MATRIX_ROW_VPOS (bottom_row, w->current_matrix),
21165 -nrows_scrolled);
21166
21167
21168 for (row -= nrows_scrolled; row < bottom_row; ++row)
21169 row->enabled_p = false;
21170
21171
21172
21173 if (pt_row)
21174 {
21175 for (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos);
21176 row < bottom_row
21177 && PT >= MATRIX_ROW_END_CHARPOS (row)
21178 && !row->ends_at_zv_p;
21179 row++)
21180 {
21181 w->cursor.vpos++;
21182 w->cursor.y = row->y;
21183 }
21184 if (row < bottom_row)
21185 {
21186
21187
21188
21189
21190 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering)))
21191 {
21192 if (!set_cursor_from_row (w, row, w->current_matrix,
21193 0, 0, 0, 0))
21194 {
21195 clear_glyph_matrix (w->desired_matrix);
21196 return false;
21197 }
21198 }
21199 else
21200 {
21201 struct glyph *glyph = row->glyphs[TEXT_AREA] + w->cursor.hpos;
21202 struct glyph *end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21203
21204 for (; glyph < end
21205 && (!BUFFERP (glyph->object)
21206 || glyph->charpos < PT);
21207 glyph++)
21208 {
21209 w->cursor.hpos++;
21210 w->cursor.x += glyph->pixel_width;
21211 }
21212 }
21213 }
21214 }
21215
21216
21217
21218
21219 if (last_text_row)
21220 adjust_window_ends (w, last_text_row, false);
21221 else
21222 w->window_end_vpos -= nrows_scrolled;
21223
21224 w->window_end_valid = false;
21225 w->desired_matrix->no_scrolling_p = true;
21226
21227 #ifdef GLYPH_DEBUG
21228 debug_method_add (w, "try_window_reusing_current_matrix 2");
21229 #endif
21230 return true;
21231 }
21232
21233 return false;
21234 }
21235
21236
21237
21238
21239
21240
21241
21242 static struct glyph_row *find_last_unchanged_at_beg_row (struct window *);
21243 static struct glyph_row *find_first_unchanged_at_end_row (struct window *,
21244 ptrdiff_t *, ptrdiff_t *);
21245 static struct glyph_row *
21246 find_last_row_displaying_text (struct glyph_matrix *, struct it *,
21247 struct glyph_row *);
21248
21249
21250
21251
21252
21253
21254
21255 static struct glyph_row *
21256 find_last_row_displaying_text (struct glyph_matrix *matrix, struct it *it,
21257 struct glyph_row *start)
21258 {
21259 struct glyph_row *row, *row_found;
21260
21261
21262
21263
21264 row_found = NULL;
21265 row = start ? start : MATRIX_FIRST_TEXT_ROW (matrix);
21266 while (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21267 {
21268 eassert (row->enabled_p);
21269 row_found = row;
21270 if (MATRIX_ROW_BOTTOM_Y (row) >= it->last_visible_y)
21271 break;
21272 ++row;
21273 }
21274
21275 return row_found;
21276 }
21277
21278
21279
21280
21281
21282
21283
21284
21285
21286
21287
21288
21289 static struct glyph_row *
21290 find_last_unchanged_at_beg_row (struct window *w)
21291 {
21292 ptrdiff_t first_changed_pos = BEG + BEG_UNCHANGED;
21293 struct glyph_row *row;
21294 struct glyph_row *row_found = NULL;
21295 int yb = window_text_bottom_y (w);
21296
21297
21298 for (row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21299 MATRIX_ROW_DISPLAYS_TEXT_P (row)
21300 && MATRIX_ROW_START_CHARPOS (row) < first_changed_pos;
21301 ++row)
21302 {
21303 if (
21304
21305 MATRIX_ROW_END_CHARPOS (row) <= first_changed_pos
21306
21307
21308 && !row->ends_at_zv_p
21309
21310
21311
21312 && !(MATRIX_ROW_END_CHARPOS (row) == first_changed_pos
21313 && (row->continued_p
21314 || row->exact_window_width_line_p))
21315
21316
21317
21318
21319
21320
21321
21322 && CHARPOS (row->end.pos) <= ZV)
21323 row_found = row;
21324
21325
21326 if (MATRIX_ROW_BOTTOM_Y (row) >= yb)
21327 break;
21328 }
21329
21330 return row_found;
21331 }
21332
21333
21334
21335
21336
21337
21338
21339
21340
21341
21342
21343
21344
21345
21346 static struct glyph_row *
21347 find_first_unchanged_at_end_row (struct window *w,
21348 ptrdiff_t *delta, ptrdiff_t *delta_bytes)
21349 {
21350 struct glyph_row *row;
21351 struct glyph_row *row_found = NULL;
21352
21353 *delta = *delta_bytes = 0;
21354
21355
21356
21357 eassert (w->window_end_valid);
21358
21359
21360
21361
21362 if (w->window_end_pos >= END_UNCHANGED)
21363 return NULL;
21364
21365
21366 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21367
21368
21369 if (MATRIX_ROW_DISPLAYS_TEXT_P (row))
21370 {
21371
21372
21373
21374
21375
21376 ptrdiff_t Z_old =
21377 MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21378 ptrdiff_t Z_BYTE_old =
21379 MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21380 ptrdiff_t last_unchanged_pos, last_unchanged_pos_old;
21381 struct glyph_row *first_text_row
21382 = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
21383
21384 *delta = Z - Z_old;
21385 *delta_bytes = Z_BYTE - Z_BYTE_old;
21386
21387
21388
21389
21390
21391
21392
21393 last_unchanged_pos = Z - END_UNCHANGED + BEG;
21394 last_unchanged_pos_old = last_unchanged_pos - *delta;
21395
21396
21397
21398 for (; row > first_text_row; --row)
21399 {
21400
21401
21402 if (!row->enabled_p || !MATRIX_ROW_DISPLAYS_TEXT_P (row))
21403 break;
21404
21405 if (MATRIX_ROW_START_CHARPOS (row) >= last_unchanged_pos_old)
21406 row_found = row;
21407 }
21408 }
21409
21410 eassert (!row_found || MATRIX_ROW_DISPLAYS_TEXT_P (row_found));
21411
21412 return row_found;
21413 }
21414
21415
21416
21417
21418
21419
21420
21421
21422 static void
21423 sync_frame_with_window_matrix_rows (struct window *w)
21424 {
21425 struct frame *f = XFRAME (w->frame);
21426 struct glyph_row *window_row, *window_row_end, *frame_row;
21427
21428
21429
21430 eassert (BUFFERP (w->contents));
21431 eassert (WINDOW_FULL_WIDTH_P (w));
21432 eassert (!FRAME_WINDOW_P (f));
21433
21434
21435
21436
21437
21438 window_row = w->current_matrix->rows;
21439 window_row_end = window_row + w->current_matrix->nrows;
21440 frame_row = f->current_matrix->rows + WINDOW_TOP_EDGE_LINE (w);
21441 while (window_row < window_row_end)
21442 {
21443 struct glyph *start = window_row->glyphs[LEFT_MARGIN_AREA];
21444 struct glyph *end = window_row->glyphs[LAST_AREA];
21445
21446 frame_row->glyphs[LEFT_MARGIN_AREA] = start;
21447 frame_row->glyphs[TEXT_AREA] = start;
21448 frame_row->glyphs[RIGHT_MARGIN_AREA] = end;
21449 frame_row->glyphs[LAST_AREA] = end;
21450
21451
21452
21453 if (!window_row->enabled_p)
21454 frame_row->enabled_p = false;
21455
21456 ++window_row, ++frame_row;
21457 }
21458 }
21459
21460
21461
21462
21463
21464
21465
21466 struct glyph_row *
21467 row_containing_pos (struct window *w, ptrdiff_t charpos,
21468 struct glyph_row *start, struct glyph_row *end, int dy)
21469 {
21470 struct glyph_row *row = start;
21471 struct glyph_row *best_row = NULL;
21472 ptrdiff_t mindif = BUF_ZV (XBUFFER (w->contents)) + 1;
21473 int last_y;
21474
21475
21476 if (row->tab_line_p)
21477 ++row;
21478 if (row->mode_line_p)
21479 ++row;
21480
21481 if ((end && row >= end) || !row->enabled_p)
21482 return NULL;
21483
21484 last_y = window_text_bottom_y (w) - dy;
21485
21486 while (true)
21487 {
21488
21489 if ((end && row >= end) || !row->enabled_p)
21490 return NULL;
21491
21492
21493
21494 if (MATRIX_ROW_BOTTOM_Y (row) > last_y)
21495 return NULL;
21496
21497
21498 if (! (MATRIX_ROW_END_CHARPOS (row) < charpos
21499 || (MATRIX_ROW_END_CHARPOS (row) == charpos
21500
21501
21502
21503
21504 && !row_for_charpos_p (row, charpos)))
21505 && charpos >= MATRIX_ROW_START_CHARPOS (row))
21506 {
21507 struct glyph *g;
21508
21509 if (NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21510 || (!best_row && !row->continued_p))
21511 return row;
21512
21513
21514
21515
21516 for (g = row->glyphs[TEXT_AREA];
21517 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
21518 g++)
21519 {
21520 if (!STRINGP (g->object))
21521 {
21522 if (g->charpos > 0 && eabs (g->charpos - charpos) < mindif)
21523 {
21524 mindif = eabs (g->charpos - charpos);
21525 best_row = row;
21526
21527 if (mindif == 0)
21528 return best_row;
21529 }
21530 }
21531 }
21532 }
21533 else if (best_row && !row->continued_p)
21534 return best_row;
21535 ++row;
21536 }
21537 }
21538
21539
21540
21541
21542
21543
21544
21545
21546
21547
21548
21549
21550
21551
21552
21553
21554
21555
21556
21557
21558
21559
21560
21561
21562
21563
21564
21565
21566
21567
21568
21569
21570
21571
21572
21573
21574
21575
21576
21577
21578
21579
21580
21581
21582 static int
21583 try_window_id (struct window *w)
21584 {
21585 struct frame *f = XFRAME (w->frame);
21586 struct glyph_matrix *current_matrix = w->current_matrix;
21587 struct glyph_matrix *desired_matrix = w->desired_matrix;
21588 struct glyph_row *last_unchanged_at_beg_row;
21589 struct glyph_row *first_unchanged_at_end_row;
21590 struct glyph_row *row;
21591 struct glyph_row *bottom_row;
21592 int bottom_vpos;
21593 struct it it;
21594 ptrdiff_t delta = 0, delta_bytes = 0, stop_pos;
21595 int dvpos, dy;
21596 struct text_pos start_pos;
21597 struct run run;
21598 int first_unchanged_at_end_vpos = 0;
21599 struct glyph_row *last_text_row, *last_text_row_at_end;
21600 struct text_pos start;
21601 ptrdiff_t first_changed_charpos, last_changed_charpos;
21602
21603 #ifdef GLYPH_DEBUG
21604 if (inhibit_try_window_id)
21605 return 0;
21606 #endif
21607
21608
21609 #if false
21610 #define GIVE_UP(X) \
21611 do { \
21612 redisplay_trace ("try_window_id give up %d\n", X); \
21613 return 0; \
21614 } while (false)
21615 #else
21616 #define GIVE_UP(X) return 0
21617 #endif
21618
21619 SET_TEXT_POS_FROM_MARKER (start, w->start);
21620
21621
21622
21623 if (MINI_WINDOW_P (w))
21624 GIVE_UP (1);
21625
21626
21627 if (windows_or_buffers_changed || f->cursor_type_changed)
21628 GIVE_UP (2);
21629
21630
21631
21632
21633 if (w->last_overlay_modified != OVERLAY_MODIFF)
21634 GIVE_UP (200);
21635
21636
21637
21638
21639
21640 if (current_buffer->clip_changed
21641 || current_buffer->prevent_redisplay_optimizations_p)
21642 GIVE_UP (3);
21643
21644
21645 if (!FRAME_WINDOW_P (f)
21646 && (!FRAME_LINE_INS_DEL_OK (f)
21647 || !WINDOW_FULL_WIDTH_P (w)))
21648 GIVE_UP (4);
21649
21650
21651 if (PT < CHARPOS (start))
21652 GIVE_UP (5);
21653
21654
21655 if (w->last_modified == 0)
21656 GIVE_UP (6);
21657
21658
21659 if (w->hscroll != 0)
21660 GIVE_UP (7);
21661
21662
21663 if (!w->window_end_valid)
21664 GIVE_UP (8);
21665
21666
21667 if (!NILP (Vshow_trailing_whitespace))
21668 GIVE_UP (11);
21669
21670
21671
21672 if (overlay_arrows_changed_p (false))
21673 GIVE_UP (12);
21674
21675
21676
21677
21678
21679 if (!NILP (BVAR (XBUFFER (w->contents), word_wrap)))
21680 GIVE_UP (21);
21681
21682
21683
21684
21685
21686
21687
21688
21689
21690 if (!NILP (BVAR (XBUFFER (w->contents), bidi_display_reordering))
21691 && NILP (BVAR (XBUFFER (w->contents), bidi_paragraph_direction)))
21692 GIVE_UP (22);
21693
21694
21695
21696 if (!NILP (BVAR (XBUFFER (w->contents), extra_line_spacing)))
21697 GIVE_UP (23);
21698
21699
21700
21701 if (EQ (Vdisplay_line_numbers, Qrelative)
21702 || EQ (Vdisplay_line_numbers, Qvisual)
21703 || (!NILP (Vdisplay_line_numbers)
21704 && NILP (Finternal_lisp_face_equal_p (Qline_number,
21705 Qline_number_current_line,
21706 w->frame))))
21707 GIVE_UP (24);
21708
21709
21710
21711
21712 if (composition_break_at_point)
21713 GIVE_UP (27);
21714
21715
21716
21717
21718
21719 if (MODIFF > SAVE_MODIFF
21720
21721 || BEG_UNCHANGED + END_UNCHANGED > Z_BYTE)
21722 {
21723 if (GPT - BEG < BEG_UNCHANGED)
21724 BEG_UNCHANGED = GPT - BEG;
21725 if (Z - GPT < END_UNCHANGED)
21726 END_UNCHANGED = Z - GPT;
21727 }
21728
21729
21730 first_changed_charpos = BEG + BEG_UNCHANGED;
21731 last_changed_charpos = Z - END_UNCHANGED;
21732
21733
21734
21735
21736
21737
21738 row = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
21739 if (MATRIX_ROW_DISPLAYS_TEXT_P (row)
21740 && ((last_changed_charpos < CHARPOS (start)
21741 && CHARPOS (start) == BEGV)
21742 || (last_changed_charpos < CHARPOS (start) - 1
21743 && FETCH_BYTE (BYTEPOS (start) - 1) == '\n')))
21744 {
21745 ptrdiff_t Z_old, Z_delta, Z_BYTE_old, Z_delta_bytes;
21746 struct glyph_row *r0;
21747
21748
21749
21750 Z_old = MATRIX_ROW_END_CHARPOS (row) + w->window_end_pos;
21751 Z_BYTE_old = MATRIX_ROW_END_BYTEPOS (row) + w->window_end_bytepos;
21752 Z_delta = Z - Z_old;
21753 Z_delta_bytes = Z_BYTE - Z_BYTE_old;
21754
21755
21756
21757
21758 if (PT >= MATRIX_ROW_END_CHARPOS (row) + Z_delta)
21759 GIVE_UP (13);
21760
21761
21762
21763
21764 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21765 if (CHARPOS (start) == MATRIX_ROW_START_CHARPOS (r0) + Z_delta
21766 && BYTEPOS (start) == MATRIX_ROW_START_BYTEPOS (r0) + Z_delta_bytes
21767
21768 && !(PT >= MATRIX_ROW_START_CHARPOS (row) + Z_delta
21769 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21770 {
21771
21772 if (Z_delta || Z_delta_bytes)
21773 {
21774 struct glyph_row *r1
21775 = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
21776 increment_matrix_positions (w->current_matrix,
21777 MATRIX_ROW_VPOS (r0, current_matrix),
21778 MATRIX_ROW_VPOS (r1, current_matrix),
21779 Z_delta, Z_delta_bytes);
21780 }
21781
21782
21783 row = row_containing_pos (w, PT, r0, NULL, 0);
21784 if (row)
21785 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21786 return 1;
21787 }
21788 }
21789
21790
21791
21792
21793
21794 if (first_changed_charpos >= MATRIX_ROW_END_CHARPOS (row)
21795
21796
21797 && (current_matrix->zv > MATRIX_ROW_END_CHARPOS (row)
21798 || first_changed_charpos == last_changed_charpos))
21799 {
21800 struct glyph_row *r0;
21801
21802
21803
21804
21805 if (PT >= MATRIX_ROW_END_CHARPOS (row))
21806 GIVE_UP (14);
21807
21808
21809
21810
21811 r0 = MATRIX_FIRST_TEXT_ROW (current_matrix);
21812 if (TEXT_POS_EQUAL_P (start, r0->minpos)
21813
21814 && !(PT >= MATRIX_ROW_START_CHARPOS (row)
21815 && MATRIX_ROW_BOTTOM_Y (row) > window_text_bottom_y (w)))
21816 {
21817
21818
21819 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
21820 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
21821
21822
21823 row = row_containing_pos (w, PT, r0, NULL, 0);
21824 if (row)
21825 set_cursor_from_row (w, row, current_matrix, 0, 0, 0, 0);
21826 return 2;
21827 }
21828 }
21829
21830
21831
21832
21833
21834
21835
21836
21837 if (CHARPOS (start) >= first_changed_charpos
21838 && CHARPOS (start) <= last_changed_charpos)
21839 GIVE_UP (15);
21840
21841
21842
21843
21844
21845 row = MATRIX_FIRST_TEXT_ROW (current_matrix);
21846 if (!TEXT_POS_EQUAL_P (start, row->minpos))
21847 GIVE_UP (16);
21848
21849
21850
21851 row = MATRIX_ROW (current_matrix, w->window_end_vpos);
21852 if (MATRIX_ROW_START_CHARPOS (row) == MATRIX_ROW_END_CHARPOS (row))
21853 GIVE_UP (20);
21854
21855
21856
21857
21858
21859 #ifdef HAVE_NTGUI
21860 if (FRAME_W32_P (f) && w32_use_visible_system_caret)
21861 GIVE_UP (25);
21862 #endif
21863
21864
21865
21866
21867
21868
21869
21870 last_unchanged_at_beg_row = find_last_unchanged_at_beg_row (w);
21871 if (last_unchanged_at_beg_row)
21872 {
21873
21874
21875
21876
21877 while ((MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row)
21878 || last_unchanged_at_beg_row->ends_in_newline_from_string_p)
21879 && last_unchanged_at_beg_row > w->current_matrix->rows)
21880 --last_unchanged_at_beg_row;
21881
21882 if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (last_unchanged_at_beg_row))
21883 GIVE_UP (17);
21884
21885 if (! init_to_row_end (&it, w, last_unchanged_at_beg_row))
21886 GIVE_UP (18);
21887
21888
21889
21890 if (it.sp > 1
21891 && it.method == GET_FROM_IMAGE && it.image_id == -1)
21892 GIVE_UP (26);
21893 start_pos = it.current.pos;
21894
21895
21896
21897
21898 it.vpos = 1 + MATRIX_ROW_VPOS (last_unchanged_at_beg_row,
21899 current_matrix);
21900 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
21901 it.current_y = MATRIX_ROW_BOTTOM_Y (last_unchanged_at_beg_row);
21902
21903 eassert (it.hpos == 0 && it.current_x == 0);
21904 }
21905 else
21906 {
21907
21908
21909 start_display (&it, w, start);
21910 it.vpos = it.first_vpos;
21911 start_pos = it.current.pos;
21912 }
21913
21914
21915
21916
21917
21918
21919
21920 first_unchanged_at_end_row
21921 = find_first_unchanged_at_end_row (w, &delta, &delta_bytes);
21922 IF_DEBUG (debug_delta = delta);
21923 IF_DEBUG (debug_delta_bytes = delta_bytes);
21924
21925
21926
21927
21928
21929
21930 stop_pos = 0;
21931 if (first_unchanged_at_end_row)
21932 {
21933 eassert (last_unchanged_at_beg_row == NULL
21934 || first_unchanged_at_end_row >= last_unchanged_at_beg_row);
21935
21936
21937
21938
21939
21940 while (MATRIX_ROW_CONTINUATION_LINE_P (first_unchanged_at_end_row)
21941 && MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
21942 && (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
21943 < it.last_visible_y))
21944 ++first_unchanged_at_end_row;
21945
21946 if (!MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row)
21947 || (MATRIX_ROW_BOTTOM_Y (first_unchanged_at_end_row)
21948 >= it.last_visible_y))
21949 first_unchanged_at_end_row = NULL;
21950 else
21951 {
21952 stop_pos = (MATRIX_ROW_START_CHARPOS (first_unchanged_at_end_row)
21953 + delta);
21954 first_unchanged_at_end_vpos
21955 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, current_matrix);
21956 eassert (stop_pos >= Z - END_UNCHANGED);
21957 }
21958 }
21959 else if (last_unchanged_at_beg_row == NULL)
21960 GIVE_UP (19);
21961
21962
21963 #ifdef GLYPH_DEBUG
21964
21965
21966
21967
21968 eassert (first_unchanged_at_end_row == NULL
21969 || MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
21970
21971 debug_last_unchanged_at_beg_vpos
21972 = (last_unchanged_at_beg_row
21973 ? MATRIX_ROW_VPOS (last_unchanged_at_beg_row, current_matrix)
21974 : -1);
21975 debug_first_unchanged_at_end_vpos = first_unchanged_at_end_vpos;
21976
21977 #endif
21978
21979
21980
21981
21982
21983 w->cursor.vpos = -1;
21984 last_text_row = NULL;
21985 overlay_arrow_seen = false;
21986 if (it.current_y < it.last_visible_y
21987 && !f->fonts_changed
21988 && (first_unchanged_at_end_row == NULL
21989 || IT_CHARPOS (it) < stop_pos))
21990 it.glyph_row->reversed_p = false;
21991 while (it.current_y < it.last_visible_y
21992 && !f->fonts_changed
21993 && (first_unchanged_at_end_row == NULL
21994 || IT_CHARPOS (it) < stop_pos))
21995 {
21996 if (display_line (&it, -1))
21997 last_text_row = it.glyph_row - 1;
21998 }
21999
22000 if (f->fonts_changed)
22001 return -1;
22002
22003
22004
22005
22006
22007
22008
22009
22010
22011
22012
22013 if (!w->window_end_valid)
22014 {
22015 clear_glyph_matrix (w->desired_matrix);
22016 return -1;
22017 }
22018
22019
22020
22021
22022 if (first_unchanged_at_end_row
22023
22024
22025 && it.current_y < it.last_visible_y)
22026 {
22027 dvpos = (it.vpos
22028 - MATRIX_ROW_VPOS (first_unchanged_at_end_row,
22029 current_matrix));
22030 dy = it.current_y - first_unchanged_at_end_row->y;
22031 run.current_y = first_unchanged_at_end_row->y;
22032 run.desired_y = run.current_y + dy;
22033 run.height = it.last_visible_y - max (run.current_y, run.desired_y);
22034 }
22035 else
22036 {
22037 delta = delta_bytes = dvpos = dy
22038 = run.current_y = run.desired_y = run.height = 0;
22039 first_unchanged_at_end_row = NULL;
22040 }
22041 IF_DEBUG ((debug_dvpos = dvpos, debug_dy = dy));
22042
22043
22044
22045
22046
22047
22048
22049
22050
22051
22052 if (w->cursor.vpos < 0)
22053 {
22054
22055 if (PT < CHARPOS (start_pos)
22056 && last_unchanged_at_beg_row)
22057 {
22058 row = row_containing_pos (w, PT,
22059 MATRIX_FIRST_TEXT_ROW (w->current_matrix),
22060 last_unchanged_at_beg_row + 1, 0);
22061 if (row)
22062 set_cursor_from_row (w, row, w->current_matrix, 0, 0, 0, 0);
22063 }
22064
22065
22066 else if (first_unchanged_at_end_row)
22067 {
22068 row = row_containing_pos (w, PT - delta,
22069 first_unchanged_at_end_row, NULL, 0);
22070 if (row)
22071 set_cursor_from_row (w, row, w->current_matrix, delta,
22072 delta_bytes, dy, dvpos);
22073 }
22074
22075
22076 if (w->cursor.vpos < 0)
22077 {
22078 clear_glyph_matrix (w->desired_matrix);
22079 return -1;
22080 }
22081 }
22082
22083
22084 {
22085 int top_scroll_margin = window_scroll_margin (w, MARGIN_IN_PIXELS);
22086 int bot_scroll_margin = top_scroll_margin;
22087 int cursor_height = MATRIX_ROW (w->desired_matrix, w->cursor.vpos)->height;
22088
22089 if (window_wants_header_line (w))
22090 top_scroll_margin += CURRENT_HEADER_LINE_HEIGHT (w);
22091 if (window_wants_tab_line (w))
22092 top_scroll_margin += CURRENT_TAB_LINE_HEIGHT (w);
22093
22094 if ((w->cursor.y < top_scroll_margin
22095 && CHARPOS (start) > BEGV)
22096
22097
22098 || (w->cursor.y
22099 + (cursor_row_fully_visible_p (w, false, true, true)
22100 ? 1
22101 : cursor_height + bot_scroll_margin)) > it.last_visible_y)
22102 {
22103 w->cursor.vpos = -1;
22104 clear_glyph_matrix (w->desired_matrix);
22105 return -1;
22106 }
22107 }
22108
22109
22110
22111
22112 if (dy && run.height)
22113 {
22114 update_begin (f);
22115
22116 if (FRAME_WINDOW_P (f))
22117 {
22118 #ifdef HAVE_WINDOW_SYSTEM
22119 gui_update_window_begin (w);
22120 FRAME_RIF (f)->clear_window_mouse_face (w);
22121 FRAME_RIF (f)->scroll_run_hook (w, &run);
22122 gui_update_window_end (w, false, false);
22123 #endif
22124 }
22125 else
22126 {
22127
22128
22129 int from_vpos
22130 = MATRIX_ROW_VPOS (first_unchanged_at_end_row, w->current_matrix);
22131 int from = WINDOW_TOP_EDGE_LINE (w) + from_vpos;
22132 int end = (WINDOW_TOP_EDGE_LINE (w)
22133 + window_wants_tab_line (w)
22134 + window_wants_header_line (w)
22135 + window_internal_height (w));
22136
22137 gui_clear_window_mouse_face (w);
22138
22139
22140 if (dvpos > 0)
22141 {
22142
22143
22144 set_terminal_window (f, end);
22145
22146
22147
22148 if (!FRAME_SCROLL_REGION_OK (f))
22149 ins_del_lines (f, end - dvpos, -dvpos);
22150
22151
22152
22153 ins_del_lines (f, from, dvpos);
22154 }
22155 else if (dvpos < 0)
22156 {
22157
22158
22159 set_terminal_window (f, end);
22160
22161
22162
22163
22164
22165 ins_del_lines (f, from + dvpos, dvpos);
22166
22167
22168
22169 if (!FRAME_SCROLL_REGION_OK (f))
22170 ins_del_lines (f, end + dvpos, -dvpos);
22171 }
22172
22173 set_terminal_window (f, 0);
22174 }
22175
22176 update_end (f);
22177 }
22178
22179
22180
22181
22182 bottom_row = MATRIX_BOTTOM_TEXT_ROW (current_matrix, w);
22183 bottom_vpos = MATRIX_ROW_VPOS (bottom_row, current_matrix);
22184 if (dvpos < 0)
22185 {
22186 rotate_matrix (current_matrix, first_unchanged_at_end_vpos + dvpos,
22187 bottom_vpos, dvpos);
22188 clear_glyph_matrix_rows (current_matrix, bottom_vpos + dvpos,
22189 bottom_vpos);
22190 }
22191 else if (dvpos > 0)
22192 {
22193 rotate_matrix (current_matrix, first_unchanged_at_end_vpos,
22194 bottom_vpos, dvpos);
22195 clear_glyph_matrix_rows (current_matrix, first_unchanged_at_end_vpos,
22196 first_unchanged_at_end_vpos + dvpos);
22197 }
22198
22199
22200
22201 if (!FRAME_WINDOW_P (f))
22202 sync_frame_with_window_matrix_rows (w);
22203
22204
22205 if (delta || delta_bytes)
22206 increment_matrix_positions (current_matrix,
22207 first_unchanged_at_end_vpos + dvpos,
22208 bottom_vpos, delta, delta_bytes);
22209
22210
22211 if (dy)
22212 shift_glyph_matrix (w, current_matrix,
22213 first_unchanged_at_end_vpos + dvpos,
22214 bottom_vpos, dy);
22215
22216 if (first_unchanged_at_end_row)
22217 {
22218 first_unchanged_at_end_row += dvpos;
22219 if (first_unchanged_at_end_row->y >= it.last_visible_y
22220 || !MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row))
22221 first_unchanged_at_end_row = NULL;
22222 }
22223
22224
22225
22226 last_text_row_at_end = NULL;
22227 if (dy < 0)
22228 {
22229
22230
22231
22232
22233
22234 int last_vpos = w->window_end_vpos + dvpos;
22235 struct glyph_row *last_row = MATRIX_ROW (current_matrix, last_vpos);
22236
22237
22238 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (last_row));
22239
22240
22241
22242
22243 if (MATRIX_ROW_BOTTOM_Y (last_row) - dy >= it.last_visible_y)
22244 {
22245 init_to_row_start (&it, w, last_row);
22246 it.vpos = last_vpos;
22247 it.current_y = last_row->y;
22248 }
22249 else
22250 {
22251 init_to_row_end (&it, w, last_row);
22252 it.vpos = 1 + last_vpos;
22253 it.current_y = MATRIX_ROW_BOTTOM_Y (last_row);
22254 ++last_row;
22255 }
22256
22257
22258
22259 it.continuation_lines_width = last_row->continuation_lines_width;
22260 it.hpos = it.current_x = 0;
22261
22262
22263 it.glyph_row = MATRIX_ROW (desired_matrix, it.vpos);
22264 while (it.current_y < it.last_visible_y && !f->fonts_changed)
22265 {
22266
22267
22268
22269
22270 SET_MATRIX_ROW_ENABLED_P (w->current_matrix, it.vpos, false);
22271 if (display_line (&it, w->cursor.vpos))
22272 last_text_row_at_end = it.glyph_row - 1;
22273 }
22274 }
22275
22276
22277 if (first_unchanged_at_end_row && !last_text_row_at_end)
22278 {
22279
22280
22281
22282
22283 eassert (MATRIX_ROW_DISPLAYS_TEXT_P (first_unchanged_at_end_row));
22284 row = find_last_row_displaying_text (w->current_matrix, &it,
22285 first_unchanged_at_end_row);
22286 eassume (row && MATRIX_ROW_DISPLAYS_TEXT_P (row));
22287 adjust_window_ends (w, row, true);
22288 eassert (w->window_end_bytepos >= 0);
22289 IF_DEBUG (debug_method_add (w, "A"));
22290 }
22291 else if (last_text_row_at_end)
22292 {
22293 adjust_window_ends (w, last_text_row_at_end, false);
22294 eassert (w->window_end_bytepos >= 0);
22295 IF_DEBUG (debug_method_add (w, "B"));
22296 }
22297 else if (last_text_row)
22298 {
22299
22300
22301
22302 adjust_window_ends (w, last_text_row, false);
22303 eassert (w->window_end_bytepos >= 0);
22304 }
22305 else if (first_unchanged_at_end_row == NULL
22306 && last_text_row == NULL
22307 && last_text_row_at_end == NULL)
22308 {
22309
22310
22311 int first_vpos = window_wants_tab_line (w) + window_wants_header_line (w);
22312 int vpos = w->window_end_vpos;
22313 struct glyph_row *current_row = current_matrix->rows + vpos;
22314 struct glyph_row *desired_row = desired_matrix->rows + vpos;
22315
22316 for (row = NULL; !row; --vpos, --current_row, --desired_row)
22317 {
22318 eassert (first_vpos <= vpos);
22319 if (desired_row->enabled_p)
22320 {
22321 if (MATRIX_ROW_DISPLAYS_TEXT_P (desired_row))
22322 row = desired_row;
22323 }
22324 else if (MATRIX_ROW_DISPLAYS_TEXT_P (current_row))
22325 row = current_row;
22326 }
22327
22328 w->window_end_vpos = vpos + 1;
22329 w->window_end_pos = Z - MATRIX_ROW_END_CHARPOS (row);
22330 w->window_end_bytepos = Z_BYTE - MATRIX_ROW_END_BYTEPOS (row);
22331 eassert (w->window_end_bytepos >= 0);
22332 IF_DEBUG (debug_method_add (w, "C"));
22333 }
22334 else
22335 emacs_abort ();
22336
22337 IF_DEBUG ((debug_end_pos = w->window_end_pos,
22338 debug_end_vpos = w->window_end_vpos));
22339
22340
22341 w->window_end_valid = false;
22342 w->desired_matrix->no_scrolling_p = true;
22343 return 3;
22344
22345 #undef GIVE_UP
22346 }
22347
22348
22349
22350
22351
22352
22353
22354 #ifdef GLYPH_DEBUG
22355
22356 void dump_glyph_row (struct glyph_row *, int, int) EXTERNALLY_VISIBLE;
22357 void dump_glyph_matrix (struct glyph_matrix *, int) EXTERNALLY_VISIBLE;
22358 void dump_glyph (struct glyph_row *, struct glyph *, int) EXTERNALLY_VISIBLE;
22359
22360
22361
22362
22363
22364
22365
22366
22367 void
22368 dump_glyph_matrix (struct glyph_matrix *matrix, int glyphs)
22369 {
22370 int i;
22371 for (i = 0; i < matrix->nrows; ++i)
22372 dump_glyph_row (MATRIX_ROW (matrix, i), i, glyphs);
22373 }
22374
22375
22376
22377
22378
22379 void
22380 dump_glyph (struct glyph_row *row, struct glyph *glyph, int area)
22381 {
22382 if (glyph->type == CHAR_GLYPH
22383 || glyph->type == GLYPHLESS_GLYPH)
22384 {
22385 fprintf (stderr,
22386 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22387 glyph - row->glyphs[TEXT_AREA],
22388 (glyph->type == CHAR_GLYPH
22389 ? 'C'
22390 : 'G'),
22391 glyph->charpos,
22392 (BUFFERP (glyph->object)
22393 ? 'B'
22394 : (STRINGP (glyph->object)
22395 ? 'S'
22396 : (NILP (glyph->object)
22397 ? '0'
22398 : '-'))),
22399 glyph->pixel_width,
22400 glyph->u.ch,
22401 (glyph->u.ch < 0x80 && glyph->u.ch >= ' '
22402 ? (int) glyph->u.ch
22403 : '.'),
22404 glyph->face_id,
22405 glyph->left_box_line_p,
22406 glyph->right_box_line_p);
22407 }
22408 else if (glyph->type == STRETCH_GLYPH)
22409 {
22410 fprintf (stderr,
22411 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22412 glyph - row->glyphs[TEXT_AREA],
22413 'S',
22414 glyph->charpos,
22415 (BUFFERP (glyph->object)
22416 ? 'B'
22417 : (STRINGP (glyph->object)
22418 ? 'S'
22419 : (NILP (glyph->object)
22420 ? '0'
22421 : '-'))),
22422 glyph->pixel_width,
22423 0u,
22424 ' ',
22425 glyph->face_id,
22426 glyph->left_box_line_p,
22427 glyph->right_box_line_p);
22428 }
22429 else if (glyph->type == IMAGE_GLYPH)
22430 {
22431 fprintf (stderr,
22432 " %5"pD"d %c %9"pD"d %c %3d 0x%06x %c %4d %1.1d%1.1d\n",
22433 glyph - row->glyphs[TEXT_AREA],
22434 'I',
22435 glyph->charpos,
22436 (BUFFERP (glyph->object)
22437 ? 'B'
22438 : (STRINGP (glyph->object)
22439 ? 'S'
22440 : (NILP (glyph->object)
22441 ? '0'
22442 : '-'))),
22443 glyph->pixel_width,
22444 (unsigned int) glyph->u.img_id,
22445 '.',
22446 glyph->face_id,
22447 glyph->left_box_line_p,
22448 glyph->right_box_line_p);
22449 }
22450 else if (glyph->type == COMPOSITE_GLYPH)
22451 {
22452 fprintf (stderr,
22453 " %5"pD"d %c %9"pD"d %c %3d 0x%06x",
22454 glyph - row->glyphs[TEXT_AREA],
22455 '+',
22456 glyph->charpos,
22457 (BUFFERP (glyph->object)
22458 ? 'B'
22459 : (STRINGP (glyph->object)
22460 ? 'S'
22461 : (NILP (glyph->object)
22462 ? '0'
22463 : '-'))),
22464 glyph->pixel_width,
22465 (unsigned int) glyph->u.cmp.id);
22466 if (glyph->u.cmp.automatic)
22467 fprintf (stderr,
22468 "[%d-%d]",
22469 glyph->slice.cmp.from, glyph->slice.cmp.to);
22470 fprintf (stderr, " . %4d %1.1d%1.1d\n",
22471 glyph->face_id,
22472 glyph->left_box_line_p,
22473 glyph->right_box_line_p);
22474 }
22475 else if (glyph->type == XWIDGET_GLYPH)
22476 {
22477 #ifndef HAVE_XWIDGETS
22478 eassume (false);
22479 #else
22480 fprintf (stderr,
22481 " %5td %4c %6td %c %3d %7p %c %4d %1.1d%1.1d\n",
22482 glyph - row->glyphs[TEXT_AREA],
22483 'X',
22484 glyph->charpos,
22485 (BUFFERP (glyph->object)
22486 ? 'B'
22487 : (STRINGP (glyph->object)
22488 ? 'S'
22489 : '-')),
22490 glyph->pixel_width,
22491 glyph->u.xwidget,
22492 '.',
22493 glyph->face_id,
22494 glyph->left_box_line_p,
22495 glyph->right_box_line_p);
22496 #endif
22497 }
22498 }
22499
22500
22501
22502
22503
22504
22505
22506 void
22507 dump_glyph_row (struct glyph_row *row, int vpos, int glyphs)
22508 {
22509 if (glyphs != 1)
22510 {
22511 fputs (("Row Start End Used oE><\\CTZFesm X Y W H V A P\n"
22512 "==============================================================================\n"),
22513 stderr);
22514 fprintf (stderr, "%3d %9"pD"d %9"pD"d %4d %1.1d%1.1d%1.1d%1.1d\
22515 %1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d%1.1d %4d %4d %4d %4d %4d %4d %4d\n",
22516 vpos,
22517 MATRIX_ROW_START_CHARPOS (row),
22518 MATRIX_ROW_END_CHARPOS (row),
22519 row->used[TEXT_AREA],
22520 row->contains_overlapping_glyphs_p,
22521 row->enabled_p,
22522 row->truncated_on_left_p,
22523 row->truncated_on_right_p,
22524 row->continued_p,
22525 MATRIX_ROW_CONTINUATION_LINE_P (row),
22526 MATRIX_ROW_DISPLAYS_TEXT_P (row),
22527 row->ends_at_zv_p,
22528 row->fill_line_p,
22529 row->ends_in_middle_of_char_p,
22530 row->starts_in_middle_of_char_p,
22531 row->mouse_face_p,
22532 row->x,
22533 row->y,
22534 row->pixel_width,
22535 row->height,
22536 row->visible_height,
22537 row->ascent,
22538 row->phys_ascent);
22539
22540 fprintf (stderr, " %9"pD"d %9"pD"d\t%5d\n", row->start.overlay_string_index,
22541 row->end.overlay_string_index,
22542 row->continuation_lines_width);
22543 fprintf (stderr, " %9"pD"d %9"pD"d\n",
22544 CHARPOS (row->start.string_pos),
22545 CHARPOS (row->end.string_pos));
22546 fprintf (stderr, " %9d %9d\n", row->start.dpvec_index,
22547 row->end.dpvec_index);
22548 }
22549
22550 if (glyphs > 1)
22551 {
22552 int area;
22553
22554 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22555 {
22556 struct glyph *glyph = row->glyphs[area];
22557 struct glyph *glyph_end = glyph + row->used[area];
22558
22559
22560 if (area == TEXT_AREA && glyph == glyph_end && glyph->charpos > 0)
22561 ++glyph_end;
22562
22563 if (glyph < glyph_end)
22564 fputs (" Glyph# Type Pos O W Code C Face LR\n",
22565 stderr);
22566
22567 for (; glyph < glyph_end; ++glyph)
22568 dump_glyph (row, glyph, area);
22569 }
22570 }
22571 else if (glyphs == 1)
22572 {
22573 int area;
22574 char s[SHRT_MAX + 4];
22575
22576 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
22577 {
22578 int i;
22579
22580 for (i = 0; i < row->used[area]; ++i)
22581 {
22582 struct glyph *glyph = row->glyphs[area] + i;
22583 if (i == row->used[area] - 1
22584 && area == TEXT_AREA
22585 && NILP (glyph->object)
22586 && glyph->type == CHAR_GLYPH
22587 && glyph->u.ch == ' ')
22588 {
22589 strcpy (&s[i], "[\\n]");
22590 i += 4;
22591 }
22592 else if (glyph->type == CHAR_GLYPH
22593 && glyph->u.ch < 0x80
22594 && glyph->u.ch >= ' ')
22595 s[i] = glyph->u.ch;
22596 else
22597 s[i] = '.';
22598 }
22599
22600 s[i] = '\0';
22601 fprintf (stderr, "%3d: (%d) '%s'\n", vpos, row->enabled_p, s);
22602 }
22603 }
22604 }
22605
22606
22607 DEFUN ("dump-glyph-matrix", Fdump_glyph_matrix,
22608 Sdump_glyph_matrix, 0, 1, "p",
22609 doc:
22610
22611
22612
22613
22614
22615 )
22616 (Lisp_Object glyphs)
22617 {
22618 struct window *w = XWINDOW (selected_window);
22619 struct buffer *buffer = XBUFFER (w->contents);
22620
22621 fprintf (stderr, "PT = %"pD"d, BEGV = %"pD"d. ZV = %"pD"d\n",
22622 BUF_PT (buffer), BUF_BEGV (buffer), BUF_ZV (buffer));
22623 fprintf (stderr, "Cursor x = %d, y = %d, hpos = %d, vpos = %d\n",
22624 w->cursor.x, w->cursor.y, w->cursor.hpos, w->cursor.vpos);
22625 fputs ("=============================================\n", stderr);
22626 dump_glyph_matrix (w->current_matrix,
22627 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 0);
22628 return Qnil;
22629 }
22630
22631
22632 DEFUN ("dump-frame-glyph-matrix", Fdump_frame_glyph_matrix,
22633 Sdump_frame_glyph_matrix, 0, 0, "", doc:
22634 )
22635 (void)
22636 {
22637 struct frame *f = XFRAME (selected_frame);
22638
22639 if (f->current_matrix)
22640 dump_glyph_matrix (f->current_matrix, 1);
22641 else
22642 fputs ("*** This frame doesn't have a frame glyph matrix ***\n", stderr);
22643 return Qnil;
22644 }
22645
22646
22647 DEFUN ("dump-glyph-row", Fdump_glyph_row, Sdump_glyph_row, 1, 2, "P",
22648 doc:
22649
22650
22651
22652
22653 )
22654 (Lisp_Object row, Lisp_Object glyphs)
22655 {
22656 struct glyph_matrix *matrix;
22657 EMACS_INT vpos;
22658
22659 if (NILP (row))
22660 {
22661 int d1, d2, d3, d4, d5, ypos;
22662 bool visible_p = pos_visible_p (XWINDOW (selected_window), PT,
22663 &d1, &d2, &d3, &d4, &d5, &ypos);
22664 if (visible_p)
22665 vpos = ypos;
22666 else
22667 vpos = 0;
22668 }
22669 else
22670 {
22671 CHECK_FIXNUM (row);
22672 vpos = XFIXNUM (row);
22673 }
22674 matrix = XWINDOW (selected_window)->current_matrix;
22675 if (vpos >= 0 && vpos < matrix->nrows)
22676 dump_glyph_row (MATRIX_ROW (matrix, vpos),
22677 vpos,
22678 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22679 return Qnil;
22680 }
22681
22682
22683 DEFUN ("dump-tab-bar-row", Fdump_tab_bar_row, Sdump_tab_bar_row, 1, 2, "P",
22684 doc:
22685
22686
22687
22688
22689
22690
22691 )
22692 (Lisp_Object row, Lisp_Object glyphs)
22693 {
22694 #if defined (HAVE_WINDOW_SYSTEM)
22695 struct frame *sf = SELECTED_FRAME ();
22696 struct glyph_matrix *m = WINDOWP (sf->tab_bar_window)
22697 ? XWINDOW (sf->tab_bar_window)->current_matrix
22698 : sf->current_matrix;
22699 EMACS_INT vpos;
22700
22701 if (NILP (row))
22702 vpos = WINDOWP (sf->tab_bar_window) ? 0 :
22703 FRAME_MENU_BAR_LINES (sf) > 0 ? 1 : 0;
22704 else
22705 {
22706 CHECK_FIXNUM (row);
22707 vpos = XFIXNUM (row);
22708 }
22709 if (vpos >= 0 && vpos < m->nrows)
22710 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22711 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22712 #endif
22713 return Qnil;
22714 }
22715
22716 DEFUN ("dump-tool-bar-row", Fdump_tool_bar_row, Sdump_tool_bar_row, 1, 2, "P",
22717 doc:
22718
22719
22720
22721
22722
22723
22724 )
22725 (Lisp_Object row, Lisp_Object glyphs)
22726 {
22727 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
22728 struct frame *sf = SELECTED_FRAME ();
22729 struct glyph_matrix *m = XWINDOW (sf->tool_bar_window)->current_matrix;
22730 EMACS_INT vpos;
22731
22732 if (NILP (row))
22733 vpos = 0;
22734 else
22735 {
22736 CHECK_FIXNUM (row);
22737 vpos = XFIXNUM (row);
22738 }
22739 if (vpos >= 0 && vpos < m->nrows)
22740 dump_glyph_row (MATRIX_ROW (m, vpos), vpos,
22741 TYPE_RANGED_FIXNUMP (int, glyphs) ? XFIXNUM (glyphs) : 2);
22742 #endif
22743 return Qnil;
22744 }
22745
22746
22747 DEFUN ("trace-redisplay", Ftrace_redisplay, Strace_redisplay, 0, 1, "P",
22748 doc:
22749 )
22750 (Lisp_Object arg)
22751 {
22752 if (NILP (arg))
22753 trace_redisplay_p = !trace_redisplay_p;
22754 else
22755 {
22756 arg = Fprefix_numeric_value (arg);
22757 trace_redisplay_p = XFIXNUM (arg) > 0;
22758 }
22759
22760 return Qnil;
22761 }
22762
22763
22764 DEFUN ("trace-to-stderr", Ftrace_to_stderr, Strace_to_stderr, 1, MANY, "",
22765 doc:
22766 )
22767 (ptrdiff_t nargs, Lisp_Object *args)
22768 {
22769 Lisp_Object s = Fformat (nargs, args);
22770 fwrite (SDATA (s), 1, SBYTES (s), stderr);
22771 return Qnil;
22772 }
22773
22774 #endif
22775
22776
22777
22778
22779
22780
22781
22782
22783
22784
22785
22786 static struct glyph_row *
22787 get_overlay_arrow_glyph_row (struct window *w, Lisp_Object overlay_arrow_string)
22788 {
22789 struct frame *f = XFRAME (WINDOW_FRAME (w));
22790 struct buffer *buffer = XBUFFER (w->contents);
22791 struct buffer *old = current_buffer;
22792 const unsigned char *arrow_string = SDATA (overlay_arrow_string);
22793 ptrdiff_t arrow_len = SBYTES (overlay_arrow_string), char_num = 0;
22794 const unsigned char *arrow_end = arrow_string + arrow_len;
22795 const unsigned char *p;
22796 struct it it;
22797 bool multibyte_p;
22798 int n_glyphs_before;
22799
22800 set_buffer_temp (buffer);
22801 init_iterator (&it, w, -1, -1, &scratch_glyph_row, DEFAULT_FACE_ID);
22802 scratch_glyph_row.reversed_p = false;
22803 it.glyph_row->used[TEXT_AREA] = 0;
22804 SET_TEXT_POS (it.position, 0, 0);
22805
22806 multibyte_p = !NILP (BVAR (buffer, enable_multibyte_characters));
22807 p = arrow_string;
22808 while (p < arrow_end)
22809 {
22810 Lisp_Object face, ilisp;
22811
22812
22813 if (multibyte_p)
22814 it.c = it.char_to_display = check_char_and_length (p, &it.len);
22815 else
22816 {
22817 it.c = it.char_to_display = *p, it.len = 1;
22818 if (! ASCII_CHAR_P (it.c))
22819 it.char_to_display = BYTE8_TO_CHAR (it.c);
22820 }
22821 p += it.len;
22822
22823
22824 ilisp = make_fixnum (char_num++);
22825 face = Fget_text_property (ilisp, Qface, overlay_arrow_string);
22826 it.face_id = compute_char_face (f, it.char_to_display, face);
22827
22828
22829 n_glyphs_before = it.glyph_row->used[TEXT_AREA];
22830 SET_TEXT_POS (it.position, -1, -1);
22831 PRODUCE_GLYPHS (&it);
22832
22833
22834
22835 if (it.current_x > it.last_visible_x)
22836 {
22837 it.glyph_row->used[TEXT_AREA] = n_glyphs_before;
22838 break;
22839 }
22840 }
22841
22842 set_buffer_temp (old);
22843 return it.glyph_row;
22844 }
22845
22846
22847
22848
22849
22850 static void
22851 insert_left_trunc_glyphs (struct it *it)
22852 {
22853 struct it truncate_it;
22854 struct glyph *from, *end, *to, *toend;
22855
22856 eassert (!FRAME_WINDOW_P (it->f)
22857 || (!it->glyph_row->reversed_p
22858 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
22859 || (it->glyph_row->reversed_p
22860 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0));
22861
22862
22863 truncate_it = *it;
22864 truncate_it.current_x = 0;
22865 truncate_it.face_id = DEFAULT_FACE_ID;
22866 truncate_it.glyph_row = &scratch_glyph_row;
22867 truncate_it.area = TEXT_AREA;
22868 truncate_it.glyph_row->used[TEXT_AREA] = 0;
22869 CHARPOS (truncate_it.position) = BYTEPOS (truncate_it.position) = -1;
22870 truncate_it.object = Qnil;
22871 produce_special_glyphs (&truncate_it, IT_TRUNCATION);
22872
22873
22874 if (!it->glyph_row->reversed_p)
22875 {
22876 short tused = truncate_it.glyph_row->used[TEXT_AREA];
22877
22878 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
22879 end = from + tused;
22880 to = it->glyph_row->glyphs[TEXT_AREA];
22881 toend = to + it->glyph_row->used[TEXT_AREA];
22882 if (FRAME_WINDOW_P (it->f))
22883 {
22884
22885
22886
22887
22888
22889
22890
22891 int w = 0;
22892 struct glyph *g = to;
22893 short used;
22894
22895
22896
22897
22898
22899
22900 it->glyph_row->x = 0;
22901 while (g < toend && w < it->truncation_pixel_width)
22902 {
22903 w += g->pixel_width;
22904 ++g;
22905 }
22906 if (g - to - tused > 0)
22907 {
22908 memmove (to + tused, g, (toend - g) * sizeof(*g));
22909 it->glyph_row->used[TEXT_AREA] -= g - to - tused;
22910 }
22911 used = it->glyph_row->used[TEXT_AREA];
22912 if (it->glyph_row->truncated_on_right_p
22913 && WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0
22914 && it->glyph_row->glyphs[TEXT_AREA][used - 2].type
22915 == STRETCH_GLYPH)
22916 {
22917 int extra = w - it->truncation_pixel_width;
22918
22919 it->glyph_row->glyphs[TEXT_AREA][used - 2].pixel_width += extra;
22920 }
22921 }
22922
22923 while (from < end)
22924 *to++ = *from++;
22925
22926
22927 if (!FRAME_WINDOW_P (it->f))
22928 {
22929 while (to < toend && CHAR_GLYPH_PADDING_P (*to))
22930 {
22931 from = truncate_it.glyph_row->glyphs[TEXT_AREA];
22932 while (from < end)
22933 *to++ = *from++;
22934 }
22935 }
22936
22937 if (to > toend)
22938 it->glyph_row->used[TEXT_AREA] = to - it->glyph_row->glyphs[TEXT_AREA];
22939 }
22940 else
22941 {
22942 short tused = truncate_it.glyph_row->used[TEXT_AREA];
22943
22944
22945
22946 end = truncate_it.glyph_row->glyphs[TEXT_AREA];
22947 from = end + truncate_it.glyph_row->used[TEXT_AREA] - 1;
22948 toend = it->glyph_row->glyphs[TEXT_AREA];
22949 to = toend + it->glyph_row->used[TEXT_AREA] - 1;
22950 if (FRAME_WINDOW_P (it->f))
22951 {
22952 int w = 0;
22953 struct glyph *g = to;
22954
22955 while (g >= toend && w < it->truncation_pixel_width)
22956 {
22957 w += g->pixel_width;
22958 --g;
22959 }
22960 if (to - g - tused > 0)
22961 to = g + tused;
22962 if (it->glyph_row->truncated_on_right_p
22963 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0
22964 && it->glyph_row->glyphs[TEXT_AREA][1].type == STRETCH_GLYPH)
22965 {
22966 int extra = w - it->truncation_pixel_width;
22967
22968 it->glyph_row->glyphs[TEXT_AREA][1].pixel_width += extra;
22969 }
22970 }
22971
22972 while (from >= end && to >= toend)
22973 *to-- = *from--;
22974 if (!FRAME_WINDOW_P (it->f))
22975 {
22976 while (to >= toend && CHAR_GLYPH_PADDING_P (*to))
22977 {
22978 from =
22979 truncate_it.glyph_row->glyphs[TEXT_AREA]
22980 + truncate_it.glyph_row->used[TEXT_AREA] - 1;
22981 while (from >= end && to >= toend)
22982 *to-- = *from--;
22983 }
22984 }
22985 if (from >= end)
22986 {
22987
22988
22989 int move_by = from - end + 1;
22990 struct glyph *g0 = it->glyph_row->glyphs[TEXT_AREA];
22991 struct glyph *g = g0 + it->glyph_row->used[TEXT_AREA] - 1;
22992
22993 for ( ; g >= g0; g--)
22994 g[move_by] = *g;
22995 while (from >= end)
22996 *to-- = *from--;
22997 it->glyph_row->used[TEXT_AREA] += move_by;
22998 }
22999 }
23000 }
23001
23002
23003 unsigned
23004 row_hash (struct glyph_row *row)
23005 {
23006 int area, k;
23007 unsigned hashval = 0;
23008
23009 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area)
23010 for (k = 0; k < row->used[area]; ++k)
23011 hashval = ((((hashval << 4) + (hashval >> 24)) & 0x0fffffff)
23012 + row->glyphs[area][k].u.val
23013 + row->glyphs[area][k].face_id
23014 + row->glyphs[area][k].padding_p
23015 + (row->glyphs[area][k].type << 2));
23016
23017 return hashval;
23018 }
23019
23020
23021
23022
23023
23024
23025
23026
23027
23028
23029
23030
23031
23032
23033
23034
23035
23036
23037 static void
23038 compute_line_metrics (struct it *it)
23039 {
23040 struct glyph_row *row = it->glyph_row;
23041
23042 if (FRAME_WINDOW_P (it->f))
23043 {
23044 int i, min_y, max_y;
23045
23046
23047
23048
23049 if (row->height == 0)
23050 {
23051 if (it->max_ascent + it->max_descent == 0)
23052 it->max_descent = it->max_phys_descent = FRAME_LINE_HEIGHT (it->f);
23053 row->ascent = it->max_ascent;
23054 row->height = it->max_ascent + it->max_descent;
23055 row->phys_ascent = it->max_phys_ascent;
23056 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
23057 row->extra_line_spacing = it->max_extra_line_spacing;
23058 }
23059
23060
23061 row->pixel_width = row->x;
23062 for (i = 0; i < row->used[TEXT_AREA]; ++i)
23063 row->pixel_width += row->glyphs[TEXT_AREA][i].pixel_width;
23064
23065 eassert (row->pixel_width >= 0);
23066 eassert (row->ascent >= 0 && row->height > 0);
23067
23068 row->overlapping_p = (MATRIX_ROW_OVERLAPS_SUCC_P (row)
23069 || MATRIX_ROW_OVERLAPS_PRED_P (row));
23070
23071
23072
23073
23074 if (row == MATRIX_FIRST_TEXT_ROW (it->w->desired_matrix)
23075 && row->phys_ascent > row->ascent)
23076 {
23077 row->height += row->phys_ascent - row->ascent;
23078 row->ascent = row->phys_ascent;
23079 }
23080
23081
23082 row->visible_height = row->height;
23083
23084 min_y = WINDOW_TAB_LINE_HEIGHT (it->w) + WINDOW_HEADER_LINE_HEIGHT (it->w);
23085 max_y = WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w);
23086
23087 if (row->y < min_y)
23088 row->visible_height -= min_y - row->y;
23089 if (row->y + row->height > max_y)
23090 row->visible_height -= row->y + row->height - max_y;
23091 }
23092 else
23093 {
23094 row->pixel_width = row->used[TEXT_AREA];
23095 if (row->continued_p)
23096 row->pixel_width -= it->continuation_pixel_width;
23097 else if (row->truncated_on_right_p)
23098 row->pixel_width -= it->truncation_pixel_width;
23099 row->ascent = row->phys_ascent = 0;
23100 row->height = row->phys_height = row->visible_height = 1;
23101 row->extra_line_spacing = 0;
23102 }
23103
23104
23105 row->hash = row_hash (row);
23106
23107 it->max_ascent = it->max_descent = 0;
23108 it->max_phys_ascent = it->max_phys_descent = 0;
23109 }
23110
23111
23112 static void
23113 clear_position (struct it *it)
23114 {
23115 it->position.charpos = 0;
23116 it->position.bytepos = 0;
23117 }
23118
23119
23120
23121
23122
23123
23124
23125
23126
23127
23128
23129
23130
23131 static bool
23132 append_space_for_newline (struct it *it, bool default_face_p)
23133 {
23134 int n = it->glyph_row->used[TEXT_AREA];
23135
23136 if (it->glyph_row->glyphs[TEXT_AREA] + n
23137 < it->glyph_row->glyphs[1 + TEXT_AREA])
23138 {
23139
23140
23141
23142
23143 enum display_element_type saved_what = it->what;
23144 int saved_c = it->c, saved_len = it->len;
23145 int saved_char_to_display = it->char_to_display;
23146 int saved_x = it->current_x;
23147 const int saved_face_id = it->face_id;
23148 bool saved_box_end = it->end_of_box_run_p;
23149 struct text_pos saved_pos = it->position;
23150 Lisp_Object saved_object = it->object;
23151 struct face *face;
23152
23153 it->what = IT_CHARACTER;
23154 clear_position (it);
23155 it->object = Qnil;
23156 it->len = 1;
23157
23158 int char_width = 1;
23159
23160 if (default_face_p
23161 #ifdef HAVE_WINDOW_SYSTEM
23162 || FRAME_WINDOW_P (it->f)
23163 #endif
23164 )
23165 {
23166 const int local_default_face_id =
23167 lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID);
23168
23169 #ifdef HAVE_WINDOW_SYSTEM
23170 if (FRAME_WINDOW_P (it->f))
23171 {
23172 struct face *default_face
23173 = FACE_FROM_ID (it->f, local_default_face_id);
23174 struct font *font = (default_face->font
23175 ? default_face->font
23176 : FRAME_FONT (it->f));
23177 char_width = (font->average_width
23178 ? font->average_width
23179 : font->space_width);
23180 }
23181 #endif
23182 if (default_face_p)
23183 it->face_id = local_default_face_id;
23184 }
23185
23186
23187
23188
23189 const int indicator_column =
23190 fill_column_indicator_column (it, char_width);
23191 int saved_end_of_box_run = it->end_of_box_run_p;
23192 bool should_keep_end_of_box_run = false;
23193
23194 if (it->current_x == indicator_column)
23195 {
23196 it->c = it->char_to_display
23197 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23198 it->face_id
23199 = merge_faces (it->w, Qfill_column_indicator,
23200 0, saved_face_id);
23201 face = FACE_FROM_ID (it->f, it->face_id);
23202 }
23203 else
23204 {
23205 it->c = it->char_to_display = ' ';
23206
23207
23208
23209 face = FACE_FROM_ID (it->f, it->face_id);
23210 it->face_id = FACE_FOR_CHAR (it->f, face, 0, -1, Qnil);
23211
23212
23213
23214
23215 if (!(it->glyph_row->reversed_p
23216
23217
23218
23219 && saved_x + FRAME_COLUMN_WIDTH (it->f) < it->last_visible_x))
23220 should_keep_end_of_box_run = true;
23221 }
23222 PRODUCE_GLYPHS (it);
23223
23224
23225 if (should_keep_end_of_box_run)
23226 it->end_of_box_run_p = saved_end_of_box_run;
23227 #ifdef HAVE_WINDOW_SYSTEM
23228 if (FRAME_WINDOW_P (it->f))
23229 {
23230
23231
23232
23233 struct glyph *g = it->glyph_row->glyphs[TEXT_AREA] + n;
23234 struct font *font = face->font ? face->font : FRAME_FONT (it->f);
23235 if (n == 0)
23236 {
23237 Lisp_Object height, total_height;
23238 int extra_line_spacing = it->extra_line_spacing;
23239 int boff = font->baseline_offset;
23240
23241 if (font->vertical_centering)
23242 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
23243
23244 it->object = saved_object;
23245 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
23246
23247
23248 height = get_it_property (it, Qline_height);
23249 if (CONSP (height)
23250 && CONSP (XCDR (height))
23251 && NILP (XCDR (XCDR (height))))
23252 {
23253 total_height = XCAR (XCDR (height));
23254 height = XCAR (height);
23255 }
23256 else
23257 total_height = Qnil;
23258 height = calc_line_height_property (it, height, font, boff, true);
23259
23260 if (it->override_ascent >= 0)
23261 {
23262 it->ascent = it->override_ascent;
23263 it->descent = it->override_descent;
23264 boff = it->override_boff;
23265 }
23266 if (EQ (height, Qt))
23267 extra_line_spacing = 0;
23268 else
23269 {
23270 Lisp_Object spacing;
23271
23272 it->phys_ascent = it->ascent;
23273 it->phys_descent = it->descent;
23274 if (!NILP (height)
23275 && XFIXNUM (height) > it->ascent + it->descent)
23276 it->ascent = XFIXNUM (height) - it->descent;
23277
23278 if (!NILP (total_height))
23279 spacing = calc_line_height_property (it, total_height, font,
23280 boff, false);
23281 else
23282 {
23283 spacing = get_it_property (it, Qline_spacing);
23284 spacing = calc_line_height_property (it, spacing, font,
23285 boff, false);
23286 }
23287 if (FIXNUMP (spacing))
23288 {
23289 extra_line_spacing = XFIXNUM (spacing);
23290 if (!NILP (total_height))
23291 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
23292 }
23293 }
23294 if (extra_line_spacing > 0)
23295 {
23296 it->descent += extra_line_spacing;
23297 if (extra_line_spacing > it->max_extra_line_spacing)
23298 it->max_extra_line_spacing = extra_line_spacing;
23299 }
23300 it->max_ascent = it->ascent;
23301 it->max_descent = it->descent;
23302
23303 it->glyph_row->height = 0;
23304 }
23305
23306 g->ascent = it->max_ascent;
23307 g->descent = it->max_descent;
23308 }
23309 #endif
23310 it->override_ascent = -1;
23311 it->constrain_row_ascent_descent_p = false;
23312 it->current_x = saved_x;
23313 it->object = saved_object;
23314 it->position = saved_pos;
23315 it->what = saved_what;
23316 it->face_id = saved_face_id;
23317 it->len = saved_len;
23318 it->c = saved_c;
23319 it->char_to_display = saved_char_to_display;
23320 it->end_of_box_run_p = saved_box_end;
23321 return true;
23322 }
23323
23324 return false;
23325 }
23326
23327
23328
23329
23330
23331
23332
23333
23334
23335 static void
23336 extend_face_to_end_of_line (struct it *it)
23337 {
23338 struct frame *f = it->f;
23339
23340
23341
23342
23343
23344
23345 if ((it->current_x >= it->last_visible_x
23346 + (!FRAME_WINDOW_P (f)
23347 && it->glyph_row->reversed_p
23348 && !it->glyph_row->continued_p))
23349
23350
23351 && !(WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23352 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0))
23353 return;
23354
23355 specpdl_ref count = SPECPDL_INDEX ();
23356
23357
23358
23359
23360 specbind (Qinhibit_quit, Qt);
23361
23362 struct face *default_face =
23363 FACE_FROM_ID_OR_NULL (f, lookup_basic_face (it->w, f, DEFAULT_FACE_ID));
23364 if (!default_face)
23365 return;
23366
23367 const int extend_face_id =
23368 (it->face_id == default_face->id || it->s != NULL)
23369 ? it->face_id
23370 : (it->glyph_row->ends_at_zv_p
23371 ? default_face->id
23372 : face_at_pos (it, LFACE_EXTEND_INDEX));
23373 unbind_to (count, Qnil);
23374
23375
23376
23377
23378 struct face *face = FACE_FROM_ID (f, (it->face_before_selective_p
23379 ? it->saved_face_id
23380 : extend_face_id));
23381
23382 if (FRAME_WINDOW_P (f)
23383 && MATRIX_ROW_DISPLAYS_TEXT_P (it->glyph_row)
23384 && face->box == FACE_NO_BOX
23385 && face->underline == FACE_NO_UNDERLINE
23386 && !face->overline_p
23387 && !face->strike_through_p
23388 && face->background == FRAME_BACKGROUND_PIXEL (f)
23389 #ifdef HAVE_WINDOW_SYSTEM
23390 && !face->stipple
23391 #endif
23392 && !it->glyph_row->reversed_p
23393 && !display_fill_column_indicator)
23394 return;
23395
23396
23397
23398 it->glyph_row->fill_line_p = true;
23399
23400 const int orig_face_id = it->face_id;
23401
23402
23403
23404
23405
23406 if (!ASCII_CHAR_P (it->c))
23407 it->face_id = FACE_FOR_CHAR (f, face, 0, -1, Qnil);
23408
23409
23410 #ifdef HAVE_WINDOW_SYSTEM
23411 if (FRAME_WINDOW_P (f))
23412 {
23413
23414
23415 if (it->glyph_row->used[TEXT_AREA] == 0)
23416 {
23417 it->glyph_row->glyphs[TEXT_AREA][0] = space_glyph;
23418 it->glyph_row->glyphs[TEXT_AREA][0].face_id = face->id;
23419 it->glyph_row->used[TEXT_AREA] = 1;
23420 }
23421
23422
23423 if (!(it->glyph_row->mode_line_p
23424 || (WINDOWP (f->tab_bar_window)
23425 && it->w == XWINDOW (f->tab_bar_window))
23426 #ifndef HAVE_EXT_TOOL_BAR
23427 || (WINDOWP (f->tool_bar_window)
23428 && it->w == XWINDOW (f->tool_bar_window))
23429 #endif
23430 ))
23431 {
23432 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23433 && it->glyph_row->used[LEFT_MARGIN_AREA] == 0)
23434 {
23435 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0] = space_glyph;
23436 it->glyph_row->glyphs[LEFT_MARGIN_AREA][0].face_id =
23437 default_face->id;
23438 it->glyph_row->used[LEFT_MARGIN_AREA] = 1;
23439 }
23440 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23441 && it->glyph_row->used[RIGHT_MARGIN_AREA] == 0)
23442 {
23443 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0] = space_glyph;
23444 it->glyph_row->glyphs[RIGHT_MARGIN_AREA][0].face_id =
23445 default_face->id;
23446 it->glyph_row->used[RIGHT_MARGIN_AREA] = 1;
23447 }
23448
23449 struct font *font = (default_face->font
23450 ? default_face->font
23451 : FRAME_FONT (f));
23452
23453 const int char_width = (font->average_width
23454 ? font->average_width
23455 : font->space_width);
23456
23457 const int indicator_column =
23458 fill_column_indicator_column (it, char_width);
23459
23460 const char saved_char = it->char_to_display;
23461 const struct text_pos saved_pos = it->position;
23462 const bool saved_avoid_cursor = it->avoid_cursor_p;
23463 const bool saved_box_start = it->start_of_box_run_p;
23464 Lisp_Object save_object = it->object;
23465 const int saved_face_id = it->face_id;
23466
23467 it->face_id = extend_face_id;
23468 it->avoid_cursor_p = true;
23469 it->object = Qnil;
23470
23471 const int stretch_height = it->ascent + it->descent;
23472 const int stretch_ascent =
23473 (stretch_height * FONT_BASE (font)) / FONT_HEIGHT (font);
23474
23475 if (indicator_column >= 0
23476 && indicator_column > it->current_x
23477 && indicator_column < it->last_visible_x)
23478 {
23479
23480
23481
23482
23483 const int stretch_width =
23484 indicator_column - it->current_x - char_width;
23485
23486 clear_position (it);
23487
23488
23489
23490 if (stretch_width > 0)
23491 {
23492 append_stretch_glyph (it, Qnil, stretch_width,
23493 stretch_height, stretch_ascent);
23494 }
23495
23496
23497
23498 if (it->current_x < indicator_column)
23499 {
23500 const int save_face_id = it->face_id;
23501 const int save_ascent = it->ascent;
23502 const int save_descent = it->descent;
23503 it->char_to_display
23504 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23505 it->face_id
23506 = merge_faces (it->w, Qfill_column_indicator,
23507 0, extend_face_id);
23508 PRODUCE_GLYPHS (it);
23509 it->face_id = save_face_id;
23510 it->ascent = save_ascent;
23511 it->descent = save_descent;
23512 }
23513 }
23514
23515
23516
23517 if (!it->glyph_row->reversed_p)
23518 {
23519 const int stretch_width = it->last_visible_x - it->current_x;
23520
23521 if (stretch_width > 0)
23522 {
23523 clear_position (it);
23524 append_stretch_glyph (it, Qnil, stretch_width,
23525 stretch_height, stretch_ascent);
23526 }
23527 }
23528
23529 it->char_to_display = saved_char;
23530 it->position = saved_pos;
23531 it->avoid_cursor_p = saved_avoid_cursor;
23532 it->start_of_box_run_p = saved_box_start;
23533 it->object = save_object;
23534 it->face_id = saved_face_id;
23535 }
23536 if (it->glyph_row->reversed_p)
23537 {
23538
23539
23540
23541
23542
23543 struct font *font = face->font ? face->font : FRAME_FONT (f);
23544 struct glyph *row_start = it->glyph_row->glyphs[TEXT_AREA];
23545 struct glyph *row_end = row_start + it->glyph_row->used[TEXT_AREA];
23546 struct glyph *g;
23547 int row_width, stretch_ascent, stretch_width;
23548 struct text_pos saved_pos;
23549 int saved_face_id;
23550 bool saved_avoid_cursor, saved_box_start;
23551
23552 for (row_width = 0, g = row_start; g < row_end; g++)
23553 row_width += g->pixel_width;
23554
23555
23556
23557
23558 if ((WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0)
23559 == (WINDOW_RIGHT_FRINGE_WIDTH (it->w) == 0)
23560 || WINDOW_RIGHT_FRINGE_WIDTH (it->w) != 0)
23561 stretch_width = window_box_width (it->w, TEXT_AREA);
23562 else
23563 stretch_width = it->last_visible_x - it->first_visible_x;
23564 stretch_width -= row_width;
23565
23566 if (stretch_width > 0)
23567 {
23568 stretch_ascent =
23569 (((it->ascent + it->descent)
23570 * FONT_BASE (font)) / FONT_HEIGHT (font));
23571 saved_pos = it->position;
23572 clear_position (it);
23573 saved_avoid_cursor = it->avoid_cursor_p;
23574 it->avoid_cursor_p = true;
23575 saved_face_id = it->face_id;
23576 saved_box_start = it->start_of_box_run_p;
23577
23578
23579
23580 it->face_id = (it->glyph_row->ends_at_zv_p ?
23581 default_face->id : face->id);
23582
23583 it->start_of_box_run_p = false;
23584 append_stretch_glyph (it, Qnil, stretch_width,
23585 it->ascent + it->descent, stretch_ascent);
23586 it->position = saved_pos;
23587 it->avoid_cursor_p = saved_avoid_cursor;
23588 it->face_id = saved_face_id;
23589 it->start_of_box_run_p = saved_box_start;
23590 }
23591
23592
23593
23594
23595 if (stretch_width < 0)
23596 it->glyph_row->x = stretch_width;
23597 }
23598 it->face_id = orig_face_id;
23599 }
23600 else
23601 #endif
23602 {
23603
23604 int saved_x = it->current_x;
23605 struct text_pos saved_pos = it->position;
23606 Lisp_Object saved_object = it->object;;
23607 enum display_element_type saved_what = it->what;
23608
23609 it->what = IT_CHARACTER;
23610 clear_position (it);
23611 it->object = Qnil;
23612 it->c = it->char_to_display = ' ';
23613 it->len = 1;
23614
23615 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
23616 && (it->glyph_row->used[LEFT_MARGIN_AREA]
23617 < WINDOW_LEFT_MARGIN_WIDTH (it->w))
23618 && !it->glyph_row->mode_line_p
23619 && face->background != FRAME_BACKGROUND_PIXEL (f))
23620 {
23621 struct glyph *g = it->glyph_row->glyphs[LEFT_MARGIN_AREA];
23622 struct glyph *e = g + it->glyph_row->used[LEFT_MARGIN_AREA];
23623
23624 for (it->current_x = 0; g < e; g++)
23625 it->current_x += g->pixel_width;
23626
23627 it->area = LEFT_MARGIN_AREA;
23628 it->face_id = default_face->id;
23629 while (it->glyph_row->used[LEFT_MARGIN_AREA]
23630 < WINDOW_LEFT_MARGIN_WIDTH (it->w)
23631 && g < it->glyph_row->glyphs[TEXT_AREA])
23632 {
23633 PRODUCE_GLYPHS (it);
23634
23635
23636 it->current_x += it->pixel_width;
23637 g++;
23638 }
23639
23640 it->current_x = saved_x;
23641 it->area = TEXT_AREA;
23642 }
23643
23644
23645
23646
23647 it->face_id = (it->glyph_row->ends_at_zv_p ?
23648 default_face->id : face->id);
23649
23650
23651
23652
23653
23654 it->current_x = it->glyph_row->used[TEXT_AREA];
23655
23656
23657
23658
23659
23660
23661
23662
23663 const int indicator_column =
23664 fill_column_indicator_column (it, 1) - it->first_visible_x;
23665
23666
23667 while (it->current_x <= it->last_visible_x)
23668 {
23669 if (it->current_x != indicator_column)
23670 PRODUCE_GLYPHS (it);
23671 else
23672 {
23673 int saved_face_id = it->face_id;
23674 it->face_id
23675 = merge_faces (it->w, Qfill_column_indicator, 0, extend_face_id);
23676 it->c = it->char_to_display
23677 = XFIXNAT (Vdisplay_fill_column_indicator_character);
23678
23679 PRODUCE_GLYPHS (it);
23680
23681 it->face_id = saved_face_id;
23682 it->c = it->char_to_display = ' ';
23683 }
23684 }
23685
23686 if (WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0
23687 && (it->glyph_row->used[RIGHT_MARGIN_AREA]
23688 < WINDOW_RIGHT_MARGIN_WIDTH (it->w))
23689 && !it->glyph_row->mode_line_p
23690 && face->background != FRAME_BACKGROUND_PIXEL (f))
23691 {
23692 struct glyph *g = it->glyph_row->glyphs[RIGHT_MARGIN_AREA];
23693 struct glyph *e = g + it->glyph_row->used[RIGHT_MARGIN_AREA];
23694
23695 for ( ; g < e; g++)
23696 it->current_x += g->pixel_width;
23697
23698 it->area = RIGHT_MARGIN_AREA;
23699 it->face_id = default_face->id;
23700 while (it->glyph_row->used[RIGHT_MARGIN_AREA]
23701 < WINDOW_RIGHT_MARGIN_WIDTH (it->w)
23702 && g < it->glyph_row->glyphs[LAST_AREA])
23703 {
23704 PRODUCE_GLYPHS (it);
23705 it->current_x += it->pixel_width;
23706 g++;
23707 }
23708
23709 it->area = TEXT_AREA;
23710 }
23711
23712
23713
23714 it->current_x = saved_x;
23715 it->object = saved_object;
23716 it->position = saved_pos;
23717 it->what = saved_what;
23718 it->face_id = orig_face_id;
23719 }
23720 }
23721
23722
23723
23724
23725
23726 static bool
23727 trailing_whitespace_p (ptrdiff_t charpos)
23728 {
23729 ptrdiff_t bytepos = CHAR_TO_BYTE (charpos);
23730 int c = 0;
23731
23732 while (bytepos < ZV_BYTE
23733 && (c = FETCH_BYTE (bytepos),
23734 c == ' ' || c == '\t'))
23735 ++bytepos;
23736
23737 if (bytepos >= ZV_BYTE || c == '\n' || c == '\r')
23738 {
23739 if (bytepos != PT_BYTE)
23740 return true;
23741 }
23742 return false;
23743 }
23744
23745
23746
23747
23748 static void
23749 highlight_trailing_whitespace (struct it *it)
23750 {
23751 struct glyph_row *row = it->glyph_row;
23752 int used = row->used[TEXT_AREA];
23753
23754 if (used)
23755 {
23756 struct glyph *start = row->glyphs[TEXT_AREA];
23757 struct glyph *glyph = start + used - 1;
23758
23759 if (row->reversed_p)
23760 {
23761
23762
23763 glyph = start;
23764 start = row->glyphs[TEXT_AREA] + used - 1;
23765 }
23766
23767
23768
23769
23770
23771 if (!row->reversed_p)
23772 {
23773 while (glyph >= start
23774 && (glyph->type == CHAR_GLYPH
23775 || glyph->type == STRETCH_GLYPH)
23776 && NILP (glyph->object))
23777 --glyph;
23778 }
23779 else
23780 {
23781 while (glyph <= start
23782 && (glyph->type == CHAR_GLYPH || glyph->type == STRETCH_GLYPH)
23783 && NILP (glyph->object))
23784 ++glyph;
23785 }
23786
23787
23788
23789
23790 if ((row->reversed_p ? glyph <= start : glyph >= start)
23791 && BUFFERP (glyph->object)
23792 && (glyph->type == STRETCH_GLYPH
23793 || (glyph->type == CHAR_GLYPH
23794 && glyph->u.ch == ' '))
23795 && trailing_whitespace_p (glyph->charpos))
23796 {
23797 int face_id = lookup_named_face (it->w, it->f, Qtrailing_whitespace, false);
23798 if (face_id < 0)
23799 return;
23800
23801 if (!row->reversed_p)
23802 {
23803 while (glyph >= start
23804 && BUFFERP (glyph->object)
23805 && (glyph->type == STRETCH_GLYPH
23806 || (glyph->type == CHAR_GLYPH
23807 && glyph->u.ch == ' ')))
23808 (glyph--)->face_id = face_id;
23809 }
23810 else
23811 {
23812 while (glyph <= start
23813 && BUFFERP (glyph->object)
23814 && (glyph->type == STRETCH_GLYPH
23815 || (glyph->type == CHAR_GLYPH
23816 && glyph->u.ch == ' ')))
23817 (glyph++)->face_id = face_id;
23818 }
23819 }
23820 }
23821 }
23822
23823
23824
23825
23826
23827 static bool
23828 row_for_charpos_p (struct glyph_row *row, ptrdiff_t charpos)
23829 {
23830 bool result = true;
23831
23832 if (charpos == CHARPOS (row->end.pos)
23833 || charpos == MATRIX_ROW_END_CHARPOS (row))
23834 {
23835
23836
23837
23838
23839
23840
23841
23842
23843 if (CHARPOS (row->end.string_pos) >= 0)
23844 {
23845 if (row->continued_p)
23846 result = true;
23847 else
23848 {
23849
23850 struct glyph *beg = row->glyphs[TEXT_AREA];
23851 struct glyph *end = beg + row->used[TEXT_AREA] - 1;
23852 struct glyph *glyph;
23853
23854 result = false;
23855 for (glyph = end; glyph >= beg; --glyph)
23856 if (STRINGP (glyph->object))
23857 {
23858 Lisp_Object prop
23859 = Fget_char_property (make_fixnum (charpos),
23860 Qdisplay, Qnil);
23861 result =
23862 (!NILP (prop)
23863 && display_prop_string_p (prop, glyph->object));
23864
23865
23866
23867 if (!result)
23868 {
23869 Lisp_Object s = glyph->object;
23870
23871 for ( ; glyph >= beg && EQ (glyph->object, s); --glyph)
23872 {
23873 ptrdiff_t gpos = glyph->charpos;
23874
23875 if (!NILP (Fget_char_property (make_fixnum (gpos),
23876 Qcursor, s)))
23877 {
23878 result = true;
23879 break;
23880 }
23881 }
23882 }
23883 break;
23884 }
23885 }
23886 }
23887 else if (MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))
23888 {
23889
23890
23891
23892
23893 if (!row->ends_in_ellipsis_p)
23894 result = row->continued_p;
23895 else
23896
23897
23898
23899
23900 result = false;
23901 }
23902
23903
23904 else
23905 result = row->ends_at_zv_p;
23906 }
23907
23908 return result;
23909 }
23910
23911
23912
23913
23914 static bool
23915 cursor_row_p (struct glyph_row *row)
23916 {
23917 return row_for_charpos_p (row, PT);
23918 }
23919
23920
23921
23922
23923
23924
23925
23926
23927 static bool
23928 push_prefix_prop (struct it *it, Lisp_Object prop)
23929 {
23930 struct text_pos pos =
23931 STRINGP (it->string) ? it->current.string_pos : it->current.pos;
23932
23933 eassert (it->method == GET_FROM_BUFFER
23934 || it->method == GET_FROM_DISPLAY_VECTOR
23935 || it->method == GET_FROM_STRING
23936 || it->method == GET_FROM_IMAGE);
23937
23938
23939
23940
23941
23942 push_it (it, &pos);
23943
23944 if (STRINGP (prop))
23945 {
23946 if (SCHARS (prop) == 0)
23947 {
23948 pop_it (it);
23949 return false;
23950 }
23951
23952 it->string = prop;
23953 it->string_from_prefix_prop_p = true;
23954 it->multibyte_p = STRING_MULTIBYTE (it->string);
23955 it->current.overlay_string_index = -1;
23956 IT_STRING_CHARPOS (*it) = IT_STRING_BYTEPOS (*it) = 0;
23957 it->end_charpos = it->string_nchars = SCHARS (it->string);
23958 it->method = GET_FROM_STRING;
23959 it->stop_charpos = 0;
23960 it->prev_stop = 0;
23961 it->base_level_stop = 0;
23962 it->cmp_it.id = -1;
23963
23964
23965
23966 if (it->bidi_p && it->bidi_it.paragraph_dir == R2L)
23967 it->paragraph_embedding = it->bidi_it.paragraph_dir;
23968 else
23969 it->paragraph_embedding = L2R;
23970
23971
23972 if (it->bidi_p)
23973 {
23974 it->bidi_it.string.lstring = it->string;
23975 it->bidi_it.string.s = NULL;
23976 it->bidi_it.string.schars = it->end_charpos;
23977 it->bidi_it.string.bufpos = IT_CHARPOS (*it);
23978 it->bidi_it.string.from_disp_str = it->string_from_display_prop_p;
23979 it->bidi_it.string.unibyte = !it->multibyte_p;
23980 it->bidi_it.w = it->w;
23981 bidi_init_it (0, 0, FRAME_WINDOW_P (it->f), &it->bidi_it);
23982 }
23983 }
23984 else if (CONSP (prop) && EQ (XCAR (prop), Qspace))
23985 {
23986 it->method = GET_FROM_STRETCH;
23987 it->object = prop;
23988 }
23989 #ifdef HAVE_WINDOW_SYSTEM
23990 else if (IMAGEP (prop))
23991 {
23992 it->what = IT_IMAGE;
23993 it->image_id = lookup_image (it->f, prop, it->face_id);
23994 it->method = GET_FROM_IMAGE;
23995 }
23996 #endif
23997 else
23998 {
23999 pop_it (it);
24000 return false;
24001 }
24002
24003 return true;
24004 }
24005
24006
24007
24008 static Lisp_Object
24009 get_it_property (struct it *it, Lisp_Object prop)
24010 {
24011 Lisp_Object position, object = it->object;
24012
24013 if (STRINGP (object))
24014 position = make_fixnum (IT_STRING_CHARPOS (*it));
24015 else if (BUFFERP (object))
24016 {
24017 position = make_fixnum (IT_CHARPOS (*it));
24018 object = it->window;
24019 }
24020 else
24021 return Qnil;
24022
24023 return Fget_char_property (position, prop, object);
24024 }
24025
24026
24027
24028
24029 static Lisp_Object
24030 get_line_prefix_it_property (struct it *it, Lisp_Object prop)
24031 {
24032 Lisp_Object prefix = get_it_property (it, prop);
24033
24034
24035
24036 if (NILP (prefix) && it->sp > 0 && STRINGP (it->object))
24037 return Fget_char_property (make_fixnum (IT_CHARPOS (*it)), prop,
24038 it->w->contents);
24039 return prefix;
24040 }
24041
24042
24043
24044 static void
24045 handle_line_prefix (struct it *it)
24046 {
24047 Lisp_Object prefix;
24048
24049 if (it->continuation_lines_width > 0)
24050 {
24051 prefix = get_line_prefix_it_property (it, Qwrap_prefix);
24052 if (NILP (prefix))
24053 prefix = Vwrap_prefix;
24054 }
24055 else
24056 {
24057 prefix = get_line_prefix_it_property (it, Qline_prefix);
24058 if (NILP (prefix))
24059 prefix = Vline_prefix;
24060 }
24061 if (! NILP (prefix) && push_prefix_prop (it, prefix))
24062 {
24063
24064
24065
24066 it->line_wrap = TRUNCATE;
24067 it->avoid_cursor_p = true;
24068 }
24069 }
24070
24071
24072
24073
24074
24075
24076
24077 static void
24078 unproduce_glyphs (struct it *it, int n)
24079 {
24080 struct glyph *glyph, *end;
24081
24082 eassert (it->glyph_row);
24083 eassert (it->glyph_row->reversed_p);
24084 eassert (it->area == TEXT_AREA);
24085 eassert (n <= it->glyph_row->used[TEXT_AREA]);
24086
24087 if (n > it->glyph_row->used[TEXT_AREA])
24088 n = it->glyph_row->used[TEXT_AREA];
24089 glyph = it->glyph_row->glyphs[TEXT_AREA] + n;
24090 end = it->glyph_row->glyphs[TEXT_AREA] + it->glyph_row->used[TEXT_AREA];
24091 for ( ; glyph < end; glyph++)
24092 glyph[-n] = *glyph;
24093 }
24094
24095
24096
24097 static void
24098 find_row_edges (struct it *it, struct glyph_row *row,
24099 ptrdiff_t min_pos, ptrdiff_t min_bpos,
24100 ptrdiff_t max_pos, ptrdiff_t max_bpos)
24101 {
24102
24103
24104
24105
24106
24107 if (min_pos <= ZV && min_pos < row->start.pos.charpos)
24108 SET_TEXT_POS (row->minpos, min_pos, min_bpos);
24109 else
24110
24111
24112
24113 row->minpos = row->start.pos;
24114 if (max_pos <= 0)
24115 {
24116 max_pos = CHARPOS (it->current.pos);
24117 max_bpos = BYTEPOS (it->current.pos);
24118 }
24119
24120
24121
24122
24123
24124
24125
24126
24127
24128
24129
24130
24131
24132
24133
24134
24135
24136 if (row->ends_at_zv_p)
24137 row->maxpos = it->current.pos;
24138 else if (row->used[TEXT_AREA])
24139 {
24140 bool seen_this_string = false;
24141 struct glyph_row *r1 = row - 1;
24142
24143
24144 if (STRINGP (it->object)
24145
24146 && row > it->w->desired_matrix->rows
24147
24148 && !r1->mode_line_p
24149
24150 && r1->ends_in_newline_from_string_p)
24151 {
24152 struct glyph *start, *end;
24153
24154
24155
24156
24157
24158 if (!r1->reversed_p)
24159 {
24160 start = r1->glyphs[TEXT_AREA];
24161 end = start + r1->used[TEXT_AREA];
24162
24163 while (end > start
24164 && NILP ((end - 1)->object)
24165 && (end - 1)->charpos <= 0)
24166 --end;
24167 if (end > start)
24168 {
24169 if (EQ ((end - 1)->object, it->object))
24170 seen_this_string = true;
24171 }
24172 else
24173
24174
24175
24176
24177
24178 seen_this_string = true;
24179 }
24180 else
24181 {
24182 end = r1->glyphs[TEXT_AREA] - 1;
24183 start = end + r1->used[TEXT_AREA];
24184 while (end < start
24185 && NILP ((end + 1)->object)
24186 && (end + 1)->charpos <= 0)
24187 ++end;
24188 if (end < start)
24189 {
24190 if (EQ ((end + 1)->object, it->object))
24191 seen_this_string = true;
24192 }
24193 else
24194 seen_this_string = true;
24195 }
24196 }
24197
24198
24199
24200 if (row->ends_in_newline_from_string_p && !seen_this_string)
24201 {
24202
24203
24204
24205
24206
24207
24208
24209
24210 if (CHARPOS (row->end.pos) > max_pos)
24211 inc_both (&max_pos, &max_bpos);
24212 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24213 }
24214 else if (CHARPOS (it->eol_pos) > 0)
24215 SET_TEXT_POS (row->maxpos,
24216 CHARPOS (it->eol_pos) + 1, BYTEPOS (it->eol_pos) + 1);
24217 else if (row->continued_p)
24218 {
24219
24220
24221
24222
24223
24224
24225 if (IT_CHARPOS (*it) == max_pos && it->method != GET_FROM_BUFFER)
24226 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24227 else
24228 {
24229 inc_both (&max_pos, &max_bpos);
24230 SET_TEXT_POS (row->maxpos, max_pos, max_bpos);
24231 }
24232 }
24233 else if (row->truncated_on_right_p)
24234
24235
24236
24237 row->maxpos = it->current.pos;
24238 else if (max_pos == min_pos && it->method != GET_FROM_BUFFER)
24239
24240 row->maxpos = row->minpos;
24241 else
24242 emacs_abort ();
24243 }
24244 else
24245 row->maxpos = it->current.pos;
24246 }
24247
24248
24249
24250 static ptrdiff_t
24251 display_count_lines_logically (ptrdiff_t start_byte, ptrdiff_t limit_byte,
24252 ptrdiff_t count, ptrdiff_t *byte_pos_ptr)
24253 {
24254 if (!display_line_numbers_widen || (BEGV == BEG && ZV == Z))
24255 return display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24256
24257 ptrdiff_t val;
24258 specpdl_ref pdl_count = SPECPDL_INDEX ();
24259 record_unwind_protect (save_restriction_restore, save_restriction_save ());
24260 labeled_restrictions_remove_in_current_buffer ();
24261 Fwiden ();
24262 val = display_count_lines (start_byte, limit_byte, count, byte_pos_ptr);
24263 unbind_to (pdl_count, Qnil);
24264 return val;
24265 }
24266
24267
24268
24269 static ptrdiff_t
24270 display_count_lines_visually (struct it *it)
24271 {
24272 struct it tem_it;
24273 ptrdiff_t to;
24274 struct text_pos from;
24275
24276
24277
24278
24279
24280
24281 if (it->lnum_bytepos > 0)
24282 return it->lnum + 1;
24283 else
24284 {
24285 specpdl_ref count = SPECPDL_INDEX ();
24286
24287 if (IT_CHARPOS (*it) <= PT)
24288 {
24289 from = it->current.pos;
24290 to = PT;
24291 }
24292 else
24293 {
24294 SET_TEXT_POS (from, PT, PT_BYTE);
24295 to = IT_CHARPOS (*it);
24296 }
24297
24298
24299
24300 specbind (Qdisplay_line_numbers, Qrelative);
24301 start_display (&tem_it, it->w, from);
24302
24303
24304
24305
24306 move_it_to (&tem_it, to, -1,
24307 tem_it.last_visible_y
24308 + (SCROLL_LIMIT + 10) * FRAME_LINE_HEIGHT (tem_it.f),
24309 -1, MOVE_TO_POS | MOVE_TO_Y);
24310 unbind_to (count, Qnil);
24311 return IT_CHARPOS (*it) <= PT ? -tem_it.vpos : tem_it.vpos;
24312 }
24313 }
24314
24315
24316
24317
24318 static void
24319 maybe_produce_line_number (struct it *it)
24320 {
24321 ptrdiff_t last_line = it->lnum;
24322 ptrdiff_t start_from, bytepos;
24323 ptrdiff_t this_line;
24324 bool first_time = false;
24325 ptrdiff_t beg_byte;
24326 ptrdiff_t z_byte;
24327 bool line_numbers_wide;
24328 void *itdata = bidi_shelve_cache ();
24329
24330 if (display_line_numbers_offset
24331 && !display_line_numbers_widen
24332 && !EQ (Vdisplay_line_numbers, Qvisual)
24333 && !EQ (Vdisplay_line_numbers, Qrelative))
24334 line_numbers_wide = true;
24335 else
24336 line_numbers_wide = display_line_numbers_widen;
24337
24338 beg_byte = line_numbers_wide ? BEG_BYTE : BEGV_BYTE;
24339 z_byte = line_numbers_wide ? Z_BYTE : ZV_BYTE;
24340
24341 if (EQ (Vdisplay_line_numbers, Qvisual))
24342 this_line = display_count_lines_visually (it);
24343 else
24344 {
24345 if (!last_line)
24346 {
24347
24348 if (it->w->base_line_number > 0
24349 && it->w->base_line_pos > 0
24350 && it->w->base_line_pos <= IT_CHARPOS (*it)
24351
24352
24353
24354
24355 && !(line_numbers_wide
24356 && (BEG_BYTE != BEGV_BYTE || Z_BYTE != ZV_BYTE))
24357 && !current_buffer->clip_changed)
24358 {
24359 start_from = CHAR_TO_BYTE (it->w->base_line_pos);
24360 last_line = it->w->base_line_number - 1;
24361 }
24362 else
24363 start_from = beg_byte;
24364 if (!it->lnum_bytepos)
24365 first_time = true;
24366 }
24367 else
24368 start_from = it->lnum_bytepos;
24369
24370
24371
24372
24373 if (!(beg_byte <= start_from && start_from <= z_byte))
24374 {
24375 last_line = 0;
24376 start_from = beg_byte;
24377 }
24378
24379 this_line =
24380 last_line + display_count_lines_logically (start_from,
24381 IT_BYTEPOS (*it),
24382 IT_CHARPOS (*it), &bytepos);
24383 eassert (this_line > 0 || (this_line == 0 && start_from == beg_byte));
24384 eassert (bytepos == IT_BYTEPOS (*it));
24385 }
24386
24387
24388 if (this_line != last_line || !it->lnum_bytepos)
24389 {
24390 it->lnum = this_line;
24391 it->lnum_bytepos = IT_BYTEPOS (*it);
24392 }
24393
24394
24395 struct it tem_it;
24396 char lnum_buf[INT_STRLEN_BOUND (ptrdiff_t) + 1];
24397 bool beyond_zv = IT_BYTEPOS (*it) >= ZV_BYTE ? true : false;
24398 ptrdiff_t lnum_offset = -1;
24399 int lnum_face_id = merge_faces (it->w, Qline_number, 0, DEFAULT_FACE_ID);
24400 int current_lnum_face_id
24401 = merge_faces (it->w, Qline_number_current_line, 0, DEFAULT_FACE_ID);
24402
24403
24404 bool save_free_realized_faces = inhibit_free_realized_faces;
24405 inhibit_free_realized_faces = true;
24406
24407 if ((EQ (Vdisplay_line_numbers, Qrelative)
24408 || EQ (Vdisplay_line_numbers, Qvisual)
24409 || lnum_face_id != current_lnum_face_id)
24410 && !it->pt_lnum)
24411 {
24412 ptrdiff_t ignored;
24413 if (PT_BYTE > it->lnum_bytepos && !EQ (Vdisplay_line_numbers, Qvisual))
24414 it->pt_lnum =
24415 this_line + display_count_lines_logically (it->lnum_bytepos, PT_BYTE,
24416 PT, &ignored);
24417 else
24418 it->pt_lnum = display_count_lines_logically (beg_byte, PT_BYTE, PT,
24419 &ignored);
24420 }
24421
24422 if (!it->lnum_width)
24423 {
24424 if (FIXNATP (Vdisplay_line_numbers_width))
24425 it->lnum_width = XFIXNAT (Vdisplay_line_numbers_width);
24426
24427
24428
24429 ptrdiff_t max_lnum;
24430
24431 if (NILP (Vdisplay_line_numbers_current_absolute)
24432 && (EQ (Vdisplay_line_numbers, Qrelative)
24433 || EQ (Vdisplay_line_numbers, Qvisual)))
24434
24435
24436 max_lnum = it->w->desired_matrix->nrows - 2;
24437 else if (EQ (Vdisplay_line_numbers, Qvisual))
24438 max_lnum = it->pt_lnum + it->w->desired_matrix->nrows - 1;
24439 else
24440 max_lnum = this_line + it->w->desired_matrix->nrows - 1 - it->vpos;
24441 max_lnum = max (1, max_lnum);
24442 it->lnum_width = max (it->lnum_width, log10 (max_lnum) + 1);
24443 eassert (it->lnum_width > 0);
24444 }
24445 if (EQ (Vdisplay_line_numbers, Qrelative))
24446 lnum_offset = it->pt_lnum;
24447 else if (EQ (Vdisplay_line_numbers, Qvisual))
24448 lnum_offset = 0;
24449 else if (display_line_numbers_offset)
24450 lnum_offset -= display_line_numbers_offset;
24451
24452
24453
24454 ptrdiff_t lnum_to_display = eabs (this_line - lnum_offset);
24455 if ((EQ (Vdisplay_line_numbers, Qrelative)
24456 || EQ (Vdisplay_line_numbers, Qvisual))
24457 && lnum_to_display == 0
24458 && !NILP (Vdisplay_line_numbers_current_absolute))
24459 lnum_to_display = it->pt_lnum + 1;
24460
24461
24462
24463
24464
24465 pint2str (lnum_buf, it->lnum_width + 1, lnum_to_display);
24466 strcat (lnum_buf, " ");
24467
24468
24469 init_iterator (&tem_it, it->w, -1, -1, &scratch_glyph_row,
24470
24471 DEFAULT_FACE_ID);
24472 scratch_glyph_row.reversed_p = false;
24473 scratch_glyph_row.used[TEXT_AREA] = 0;
24474 SET_TEXT_POS (tem_it.position, 0, 0);
24475 tem_it.avoid_cursor_p = true;
24476 tem_it.bidi_p = true;
24477 tem_it.bidi_it.type = WEAK_EN;
24478
24479
24480
24481 tem_it.bidi_it.resolved_level = 2;
24482
24483
24484
24485 int width_limit =
24486 tem_it.last_visible_x - tem_it.first_visible_x
24487 - 3 * FRAME_COLUMN_WIDTH (it->f);
24488
24489 tem_it.face_id = lnum_face_id;
24490
24491
24492 if (lnum_face_id != current_lnum_face_id
24493 && (EQ (Vdisplay_line_numbers, Qvisual)
24494 ? this_line == 0
24495 : this_line == it->pt_lnum)
24496 && it->what != IT_EOB)
24497 tem_it.face_id = current_lnum_face_id;
24498 else if (!beyond_zv)
24499 {
24500 if (display_line_numbers_major_tick > 0
24501 && (lnum_to_display % display_line_numbers_major_tick == 0))
24502 tem_it.face_id = merge_faces (it->w, Qline_number_major_tick,
24503 0, DEFAULT_FACE_ID);
24504 else if (display_line_numbers_minor_tick > 0
24505 && (lnum_to_display % display_line_numbers_minor_tick == 0))
24506 tem_it.face_id = merge_faces (it->w, Qline_number_minor_tick,
24507 0, DEFAULT_FACE_ID);
24508 }
24509
24510
24511 for (const char *p = lnum_buf; *p; p++)
24512 {
24513
24514
24515 if (beyond_zv
24516
24517 || (!EQ (Vdisplay_line_numbers, Qvisual)
24518 && (it->continuation_lines_width > 0
24519 || (this_line == last_line && !first_time))))
24520 tem_it.c = tem_it.char_to_display = ' ';
24521 else
24522 tem_it.c = tem_it.char_to_display = *p;
24523 tem_it.len = 1;
24524
24525 SET_TEXT_POS (tem_it.position, -1, -1);
24526 PRODUCE_GLYPHS (&tem_it);
24527
24528
24529
24530 if (tem_it.current_x >= width_limit)
24531 {
24532 it->lnum_width = 0;
24533 it->lnum_pixel_width = 0;
24534 bidi_unshelve_cache (itdata, false);
24535 inhibit_free_realized_faces = save_free_realized_faces;
24536 return;
24537 }
24538 }
24539
24540 inhibit_free_realized_faces = save_free_realized_faces;
24541
24542
24543 it->lnum_pixel_width = tem_it.current_x;
24544
24545 struct glyph *g = scratch_glyph_row.glyphs[TEXT_AREA];
24546 struct glyph *e = g + scratch_glyph_row.used[TEXT_AREA];
24547 struct glyph *p = it->glyph_row ? it->glyph_row->glyphs[TEXT_AREA] : NULL;
24548 short *u = it->glyph_row ? &it->glyph_row->used[TEXT_AREA] : NULL;
24549
24550 eassert (it->glyph_row == NULL || it->glyph_row->used[TEXT_AREA] == 0);
24551
24552 for ( ; g < e; g++)
24553 {
24554 it->current_x += g->pixel_width;
24555
24556
24557
24558 if (it->current_x > it->first_visible_x)
24559 it->hpos++;
24560 if (p)
24561 {
24562 *p++ = *g;
24563 (*u)++;
24564 }
24565 }
24566
24567
24568
24569
24570 if (!beyond_zv)
24571 {
24572 if (it->glyph_row)
24573 {
24574 struct glyph_row *row = it->glyph_row;
24575
24576 it->max_ascent = max (row->ascent, tem_it.max_ascent);
24577 it->max_descent = max (row->height - row->ascent, tem_it.max_descent);
24578 it->max_phys_ascent = max (row->phys_ascent, tem_it.max_phys_ascent);
24579 it->max_phys_descent = max (row->phys_height - row->phys_ascent,
24580 tem_it.max_phys_descent);
24581 }
24582 else
24583 {
24584 it->max_ascent = max (it->max_ascent, tem_it.max_ascent);
24585 it->max_descent = max (it->max_descent, tem_it.max_descent);
24586 it->max_phys_ascent = max (it->max_phys_ascent,
24587 tem_it.max_phys_ascent);
24588 it->max_phys_descent = max (it->max_phys_descent,
24589 tem_it.max_phys_descent);
24590 }
24591 }
24592
24593 it->line_number_produced_p = true;
24594
24595 bidi_unshelve_cache (itdata, false);
24596 }
24597
24598
24599
24600 static bool
24601 should_produce_line_number (struct it *it)
24602 {
24603 if (NILP (Vdisplay_line_numbers))
24604 return false;
24605
24606
24607 if (MINI_WINDOW_P (it->w))
24608 return false;
24609
24610 #ifdef HAVE_WINDOW_SYSTEM
24611
24612 if (FRAME_TOOLTIP_P (XFRAME (WINDOW_FRAME (it->w))))
24613 return false;
24614 #endif
24615
24616
24617
24618
24619
24620 Lisp_Object val = Fget_char_property (make_fixnum (IT_CHARPOS (*it)),
24621 Qdisplay_line_numbers_disable,
24622 it->window);
24623
24624
24625
24626 if (NILP (val) && IT_CHARPOS (*it) >= ZV)
24627 val = disable_line_numbers_overlay_at_eob ();
24628 return NILP (val) ? true : false;
24629 }
24630
24631
24632
24633
24634
24635 static bool
24636 row_text_area_empty (struct glyph_row *row)
24637 {
24638 if (!row->reversed_p)
24639 {
24640 for (struct glyph *g = row->glyphs[TEXT_AREA];
24641 g < row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
24642 g++)
24643 if (!NILP (g->object) || g->charpos > 0)
24644 return false;
24645 }
24646 else
24647 {
24648 for (struct glyph *g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
24649 g > row->glyphs[TEXT_AREA];
24650 g--)
24651 if (!NILP ((g - 1)->object) || (g - 1)->charpos > 0)
24652 return false;
24653 }
24654
24655 return true;
24656 }
24657
24658
24659
24660
24661
24662
24663
24664
24665 static bool
24666 display_line (struct it *it, int cursor_vpos)
24667 {
24668 struct glyph_row *row = it->glyph_row;
24669 Lisp_Object overlay_arrow_string;
24670 struct it wrap_it;
24671 void *wrap_data = NULL;
24672 bool may_wrap = false;
24673 int wrap_x UNINIT;
24674 int wrap_row_used = -1;
24675 int wrap_row_ascent UNINIT, wrap_row_height UNINIT;
24676 int wrap_row_phys_ascent UNINIT, wrap_row_phys_height UNINIT;
24677 int wrap_row_extra_line_spacing UNINIT;
24678 ptrdiff_t wrap_row_min_pos UNINIT, wrap_row_min_bpos UNINIT;
24679 ptrdiff_t wrap_row_max_pos UNINIT, wrap_row_max_bpos UNINIT;
24680 int cvpos;
24681 ptrdiff_t min_pos = ZV + 1, max_pos = 0;
24682 ptrdiff_t min_bpos UNINIT, max_bpos UNINIT;
24683 bool pending_handle_line_prefix = false;
24684 int tab_line = window_wants_tab_line (it->w);
24685 int header_line = window_wants_header_line (it->w);
24686 bool hscroll_this_line = (cursor_vpos >= 0
24687 && it->vpos == cursor_vpos - tab_line - header_line
24688 && hscrolling_current_line_p (it->w));
24689 int first_visible_x = it->first_visible_x;
24690 int last_visible_x = it->last_visible_x;
24691 int x_incr = 0;
24692
24693
24694 eassert (it->hpos == 0 && it->current_x == 0);
24695
24696 if (MATRIX_ROW_VPOS (row, it->w->desired_matrix)
24697 >= it->w->desired_matrix->nrows)
24698 {
24699 it->w->nrows_scale_factor++;
24700 it->f->fonts_changed = true;
24701 return false;
24702 }
24703
24704
24705 prepare_desired_row (it->w, row, false);
24706
24707 row->y = it->current_y;
24708 row->start = it->start;
24709 row->continuation_lines_width = it->continuation_lines_width;
24710 row->displays_text_p = true;
24711 row->starts_in_middle_of_char_p = it->starts_in_middle_of_char_p;
24712 it->starts_in_middle_of_char_p = false;
24713 it->stretch_adjust = 0;
24714 it->line_number_produced_p = false;
24715
24716
24717
24718
24719 if (hscroll_this_line)
24720 x_incr =
24721 (window_hscroll_limited (it->w, it->f) - it->w->min_hscroll)
24722 * FRAME_COLUMN_WIDTH (it->f);
24723
24724 bool line_number_needed = should_produce_line_number (it);
24725
24726
24727
24728
24729 if (it->current_x < it->first_visible_x + x_incr)
24730 {
24731 enum move_it_result move_result;
24732
24733 this_line_min_pos = row->start.pos;
24734 if (hscroll_this_line)
24735 {
24736 it->first_visible_x += x_incr;
24737 it->last_visible_x += x_incr;
24738 }
24739 if (current_buffer->long_line_optimizations_p
24740 && it->line_wrap == TRUNCATE
24741 && window_hscroll_limited (it->w, it->f) > large_hscroll_threshold)
24742 {
24743
24744
24745
24746
24747 ptrdiff_t chars_to_skip =
24748 it->first_visible_x / FRAME_COLUMN_WIDTH (it->f);
24749 move_result = fast_move_it_horizontally (it, chars_to_skip);
24750
24751 if (move_result == MOVE_X_REACHED)
24752 it->current_x = it->first_visible_x;
24753 else
24754 it->current_x = it->first_visible_x - FRAME_COLUMN_WIDTH (it->f);
24755 }
24756 else
24757 move_result = move_it_in_display_line_to (it, ZV, it->first_visible_x,
24758 MOVE_TO_POS | MOVE_TO_X);
24759
24760
24761
24762
24763
24764
24765 if (it->current_x < it->first_visible_x
24766 && (move_result == MOVE_NEWLINE_OR_CR
24767 || move_result == MOVE_POS_MATCH_OR_ZV))
24768 it->current_x = it->first_visible_x;
24769
24770
24771
24772 it->line_number_produced_p = false;
24773
24774
24775
24776
24777
24778
24779
24780
24781 min_pos = CHARPOS (this_line_min_pos);
24782 min_bpos = BYTEPOS (this_line_min_pos);
24783
24784
24785 if (line_number_needed)
24786 maybe_produce_line_number (it);
24787 }
24788 else if (it->area == TEXT_AREA)
24789 {
24790
24791 if (line_number_needed)
24792 maybe_produce_line_number (it);
24793
24794
24795
24796 handle_line_prefix (it);
24797 }
24798 else
24799 {
24800
24801
24802
24803
24804
24805
24806
24807 pending_handle_line_prefix = true;
24808 }
24809
24810
24811
24812 row->ascent = it->max_ascent;
24813 row->height = it->max_ascent + it->max_descent;
24814 row->phys_ascent = it->max_phys_ascent;
24815 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
24816 row->extra_line_spacing = it->max_extra_line_spacing;
24817
24818
24819 #define RECORD_MAX_MIN_POS(IT) \
24820 do \
24821 { \
24822 bool composition_p \
24823 = !STRINGP ((IT)->string) && ((IT)->what == IT_COMPOSITION); \
24824 ptrdiff_t current_pos = \
24825 composition_p ? (IT)->cmp_it.charpos \
24826 : IT_CHARPOS (*(IT)); \
24827 ptrdiff_t current_bpos = \
24828 composition_p ? CHAR_TO_BYTE (current_pos) \
24829 : IT_BYTEPOS (*(IT)); \
24830 if (current_pos < min_pos) \
24831 { \
24832 min_pos = current_pos; \
24833 min_bpos = current_bpos; \
24834 } \
24835 if (IT_CHARPOS (*it) > max_pos) \
24836 { \
24837 max_pos = IT_CHARPOS (*it); \
24838 max_bpos = IT_BYTEPOS (*it); \
24839 } \
24840 } \
24841 while (false)
24842
24843
24844
24845 while (true)
24846 {
24847 int n_glyphs_before, hpos_before, x_before;
24848 int x, nglyphs;
24849 int ascent = 0, descent = 0, phys_ascent = 0, phys_descent = 0;
24850
24851
24852
24853 if (!get_next_display_element (it))
24854 {
24855 bool row_has_glyphs = false;
24856
24857
24858
24859
24860 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
24861 row->exact_window_width_line_p = true;
24862 else if ((append_space_for_newline (it, true)
24863 && row->used[TEXT_AREA] == 1)
24864 || row->used[TEXT_AREA] == 0
24865 || (row_has_glyphs = row_text_area_empty (row)))
24866 {
24867 row->glyphs[TEXT_AREA]->charpos = -1;
24868
24869
24870 if (!row_has_glyphs)
24871 row->displays_text_p = false;
24872
24873 if (!NILP (BVAR (XBUFFER (it->w->contents), indicate_empty_lines))
24874 && (!MINI_WINDOW_P (it->w)))
24875 row->indicate_empty_line_p = true;
24876 }
24877
24878 it->continuation_lines_width = 0;
24879
24880
24881
24882
24883 it->font_height = Qnil;
24884 it->voffset = 0;
24885 row->ends_at_zv_p = true;
24886
24887
24888
24889
24890
24891
24892
24893
24894 if (row->reversed_p
24895 || lookup_basic_face (it->w, it->f, DEFAULT_FACE_ID)
24896 != DEFAULT_FACE_ID)
24897 extend_face_to_end_of_line (it);
24898 break;
24899 }
24900
24901
24902
24903 n_glyphs_before = row->used[TEXT_AREA];
24904 x = it->current_x;
24905
24906
24907
24908 if (it->line_wrap != TRUNCATE)
24909 {
24910 ascent = it->max_ascent;
24911 descent = it->max_descent;
24912 phys_ascent = it->max_phys_ascent;
24913 phys_descent = it->max_phys_descent;
24914
24915 if (it->line_wrap == WORD_WRAP && it->area == TEXT_AREA)
24916 {
24917 bool next_may_wrap = may_wrap;
24918
24919 if (char_can_wrap_after (it))
24920 next_may_wrap = true;
24921 else
24922 next_may_wrap = false;
24923
24924 if (may_wrap && char_can_wrap_before (it))
24925 {
24926 SAVE_IT (wrap_it, *it, wrap_data);
24927 wrap_x = x;
24928 wrap_row_used = row->used[TEXT_AREA];
24929 wrap_row_ascent = row->ascent;
24930 wrap_row_height = row->height;
24931 wrap_row_phys_ascent = row->phys_ascent;
24932 wrap_row_phys_height = row->phys_height;
24933 wrap_row_extra_line_spacing = row->extra_line_spacing;
24934 wrap_row_min_pos = min_pos;
24935 wrap_row_min_bpos = min_bpos;
24936 wrap_row_max_pos = max_pos;
24937 wrap_row_max_bpos = max_bpos;
24938 }
24939
24940 may_wrap = next_may_wrap;
24941 }
24942 }
24943
24944 PRODUCE_GLYPHS (it);
24945
24946
24947
24948 if (it->area != TEXT_AREA)
24949 {
24950 row->ascent = max (row->ascent, it->max_ascent);
24951 row->height = max (row->height, it->max_ascent + it->max_descent);
24952 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
24953 row->phys_height = max (row->phys_height,
24954 it->max_phys_ascent + it->max_phys_descent);
24955 row->extra_line_spacing = max (row->extra_line_spacing,
24956 it->max_extra_line_spacing);
24957 set_iterator_to_next (it, true);
24958
24959
24960
24961 if (it->area == TEXT_AREA && pending_handle_line_prefix)
24962 {
24963
24964 if (line_number_needed)
24965 maybe_produce_line_number (it);
24966
24967 pending_handle_line_prefix = false;
24968 handle_line_prefix (it);
24969 }
24970 continue;
24971 }
24972
24973
24974
24975
24976
24977
24978
24979
24980
24981
24982 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
24983 hpos_before = it->hpos;
24984 x_before = x;
24985
24986 if (
24987 nglyphs > 0
24988
24989 && it->current_x < it->last_visible_x)
24990 {
24991 it->hpos += nglyphs;
24992 row->ascent = max (row->ascent, it->max_ascent);
24993 row->height = max (row->height, it->max_ascent + it->max_descent);
24994 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
24995 row->phys_height = max (row->phys_height,
24996 it->max_phys_ascent + it->max_phys_descent);
24997 row->extra_line_spacing = max (row->extra_line_spacing,
24998 it->max_extra_line_spacing);
24999 if (it->current_x - it->pixel_width < it->first_visible_x
25000
25001
25002
25003 && !line_number_needed
25004
25005
25006
25007
25008 && !row->reversed_p)
25009 row->x = x - it->first_visible_x;
25010
25011
25012 if (it->bidi_p)
25013 RECORD_MAX_MIN_POS (it);
25014 }
25015 else
25016 {
25017 int i, new_x;
25018 struct glyph *glyph;
25019
25020 for (i = 0; i < nglyphs; ++i, x = new_x)
25021 {
25022
25023
25024
25025 if (!row->reversed_p)
25026 glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
25027 else
25028 glyph = row->glyphs[TEXT_AREA] + nglyphs - 1 - i;
25029 new_x = x + glyph->pixel_width;
25030
25031 if (
25032 it->line_wrap != TRUNCATE
25033 && (
25034 new_x > it->last_visible_x
25035
25036 || (new_x == it->last_visible_x
25037 && FRAME_WINDOW_P (it->f)
25038 && (row->reversed_p
25039 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25040 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)))))
25041 {
25042
25043
25044 if (it->hpos == 0
25045 || (new_x == it->last_visible_x
25046 && FRAME_WINDOW_P (it->f)
25047 && (row->reversed_p
25048 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25049 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))))
25050 {
25051
25052
25053
25054
25055 row->continued_p = true;
25056 it->current_x = new_x;
25057 it->continuation_lines_width += new_x;
25058 ++it->hpos;
25059 if (i == nglyphs - 1)
25060 {
25061
25062
25063 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it)
25064 && wrap_row_used > 0
25065
25066
25067
25068
25069
25070
25071
25072
25073
25074
25075 && (!may_wrap || !char_can_wrap_before (it)))
25076 goto back_to_wrap;
25077
25078
25079
25080
25081 if (it->bidi_p)
25082 RECORD_MAX_MIN_POS (it);
25083 set_iterator_to_next (it, true);
25084 if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25085 {
25086 if (!get_next_display_element (it))
25087 {
25088 row->exact_window_width_line_p = true;
25089 it->continuation_lines_width = 0;
25090 it->font_height = Qnil;
25091 it->voffset = 0;
25092 row->continued_p = false;
25093 row->ends_at_zv_p = true;
25094 }
25095 else if (ITERATOR_AT_END_OF_LINE_P (it))
25096 {
25097 row->continued_p = false;
25098 row->exact_window_width_line_p = true;
25099 }
25100
25101
25102 else if (wrap_row_used > 0
25103
25104
25105
25106
25107
25108
25109
25110
25111
25112 && (!may_wrap || !char_can_wrap_before (it)))
25113 goto back_to_wrap;
25114
25115 }
25116 }
25117 else if (it->bidi_p)
25118 RECORD_MAX_MIN_POS (it);
25119 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25120 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25121 extend_face_to_end_of_line (it);
25122 }
25123 else if (CHAR_GLYPH_PADDING_P (*glyph)
25124 && !FRAME_WINDOW_P (it->f))
25125 {
25126
25127
25128
25129 if (row->reversed_p)
25130 unproduce_glyphs (it, row->used[TEXT_AREA]
25131 - n_glyphs_before);
25132 row->used[TEXT_AREA] = n_glyphs_before;
25133
25134
25135
25136 while (row->glyphs[TEXT_AREA] + row->used[TEXT_AREA]
25137 < row->glyphs[1 + TEXT_AREA])
25138 produce_special_glyphs (it, IT_CONTINUATION);
25139
25140 row->continued_p = true;
25141 it->current_x = x_before;
25142 it->continuation_lines_width += x_before;
25143
25144
25145
25146 it->max_ascent = ascent;
25147 it->max_descent = descent;
25148 it->max_phys_ascent = phys_ascent;
25149 it->max_phys_descent = phys_descent;
25150 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25151 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25152 extend_face_to_end_of_line (it);
25153 }
25154 else if (wrap_row_used > 0)
25155 {
25156 back_to_wrap:
25157 if (row->reversed_p)
25158 unproduce_glyphs (it,
25159 row->used[TEXT_AREA] - wrap_row_used);
25160 RESTORE_IT (it, &wrap_it, wrap_data);
25161 it->continuation_lines_width += wrap_x;
25162 row->used[TEXT_AREA] = wrap_row_used;
25163 row->ascent = wrap_row_ascent;
25164 row->height = wrap_row_height;
25165 row->phys_ascent = wrap_row_phys_ascent;
25166 row->phys_height = wrap_row_phys_height;
25167 row->extra_line_spacing = wrap_row_extra_line_spacing;
25168 min_pos = wrap_row_min_pos;
25169 min_bpos = wrap_row_min_bpos;
25170 max_pos = wrap_row_max_pos;
25171 max_bpos = wrap_row_max_bpos;
25172 row->continued_p = true;
25173 row->ends_at_zv_p = false;
25174 row->exact_window_width_line_p = false;
25175
25176
25177
25178 extend_face_to_end_of_line (it);
25179 }
25180 else if ((it->what == IT_CHARACTER
25181 || it->what == IT_STRETCH
25182 || it->what == IT_COMPOSITION)
25183 && it->c == '\t' && FRAME_WINDOW_P (it->f))
25184 {
25185
25186
25187
25188
25189
25190 if ((row->reversed_p
25191 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25192 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25193 produce_special_glyphs (it, IT_CONTINUATION);
25194 it->continuation_lines_width += it->last_visible_x;
25195 row->ends_in_middle_of_char_p = true;
25196 row->continued_p = true;
25197 glyph->pixel_width = it->last_visible_x - x;
25198 it->starts_in_middle_of_char_p = true;
25199 if (WINDOW_LEFT_MARGIN_WIDTH (it->w) > 0
25200 || WINDOW_RIGHT_MARGIN_WIDTH (it->w) > 0)
25201 extend_face_to_end_of_line (it);
25202 }
25203 else
25204 {
25205
25206
25207
25208 if (row->reversed_p)
25209 unproduce_glyphs (it, row->used[TEXT_AREA]
25210 - (n_glyphs_before + i));
25211 row->used[TEXT_AREA] = n_glyphs_before + i;
25212
25213
25214 it->current_x = x_before;
25215 it->continuation_lines_width += x;
25216 if (!FRAME_WINDOW_P (it->f)
25217 || (row->reversed_p
25218 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25219 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25220 produce_special_glyphs (it, IT_CONTINUATION);
25221 row->continued_p = true;
25222
25223 extend_face_to_end_of_line (it);
25224
25225 if (nglyphs > 1 && i > 0)
25226 {
25227 row->ends_in_middle_of_char_p = true;
25228 it->starts_in_middle_of_char_p = true;
25229 }
25230
25231
25232
25233 it->max_ascent = ascent;
25234 it->max_descent = descent;
25235 it->max_phys_ascent = phys_ascent;
25236 it->max_phys_descent = phys_descent;
25237 }
25238
25239 break;
25240 }
25241 else if (new_x > it->first_visible_x)
25242 {
25243
25244 ++it->hpos;
25245
25246
25247
25248
25249 if (it->bidi_p)
25250 RECORD_MAX_MIN_POS (it);
25251
25252 if (x < it->first_visible_x && !row->reversed_p
25253 && !line_number_needed)
25254
25255
25256
25257
25258
25259
25260 row->x = x - it->first_visible_x;
25261
25262
25263
25264
25265
25266
25267 if (row->reversed_p
25268 && new_x > it->last_visible_x
25269 && !line_number_needed
25270 && !(it->line_wrap == TRUNCATE
25271 && WINDOW_LEFT_FRINGE_WIDTH (it->w) == 0))
25272 {
25273 eassert (FRAME_WINDOW_P (it->f));
25274 row->x = it->last_visible_x - new_x;
25275 }
25276 }
25277 else
25278 {
25279
25280
25281
25282
25283
25284 eassert (it->first_visible_x <= it->last_visible_x);
25285 }
25286 }
25287
25288
25289 if (it->bidi_p && nglyphs == 0)
25290 RECORD_MAX_MIN_POS (it);
25291
25292 row->ascent = max (row->ascent, it->max_ascent);
25293 row->height = max (row->height, it->max_ascent + it->max_descent);
25294 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
25295 row->phys_height = max (row->phys_height,
25296 it->max_phys_ascent + it->max_phys_descent);
25297 row->extra_line_spacing = max (row->extra_line_spacing,
25298 it->max_extra_line_spacing);
25299
25300
25301 if (row->continued_p || row->ends_at_zv_p)
25302 break;
25303 }
25304
25305 at_end_of_line:
25306
25307
25308
25309 if (ITERATOR_AT_END_OF_LINE_P (it))
25310 {
25311 int used_before = row->used[TEXT_AREA];
25312
25313 row->ends_in_newline_from_string_p = STRINGP (it->object);
25314
25315
25316
25317 if (!IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25318 append_space_for_newline (it, false);
25319
25320
25321 extend_face_to_end_of_line (it);
25322
25323
25324 if (used_before == 0)
25325 row->glyphs[TEXT_AREA]->charpos = CHARPOS (it->position);
25326
25327
25328
25329 it->eol_pos = it->current.pos;
25330
25331
25332 set_iterator_to_next (it, true);
25333 it->continuation_lines_width = 0;
25334 break;
25335 }
25336
25337
25338
25339
25340
25341
25342
25343
25344 bool overwide_wrap_prefix =
25345 CONSP (it->object) && EQ (XCAR (it->object), Qspace)
25346 && it->sp > 0 && it->method == GET_FROM_STRETCH
25347 && it->current_x >= it->last_visible_x
25348 && it->continuation_lines_width > 0
25349 && it->line_wrap == TRUNCATE && it->stack[0].line_wrap != TRUNCATE;
25350
25351
25352
25353 if (!overwide_wrap_prefix)
25354 set_iterator_to_next (it, true);
25355
25356
25357
25358 if (it->line_wrap == TRUNCATE
25359 && ((FRAME_WINDOW_P (it->f)
25360
25361
25362
25363
25364 && ((row->reversed_p
25365 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25366 : WINDOW_RIGHT_FRINGE_WIDTH (it->w))
25367 || it->what == IT_IMAGE))
25368 ? (it->current_x >= it->last_visible_x)
25369 : (it->current_x > it->last_visible_x)))
25370 {
25371
25372 if (!FRAME_WINDOW_P (it->f)
25373 || (row->reversed_p
25374 ? WINDOW_LEFT_FRINGE_WIDTH (it->w)
25375 : WINDOW_RIGHT_FRINGE_WIDTH (it->w)) == 0)
25376 {
25377 int i, n;
25378
25379 if (!row->reversed_p)
25380 {
25381 for (i = row->used[TEXT_AREA] - 1; i > 0; --i)
25382 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25383 break;
25384 }
25385 else
25386 {
25387 for (i = 0; i < row->used[TEXT_AREA]; i++)
25388 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][i]))
25389 break;
25390
25391
25392
25393
25394
25395 unproduce_glyphs (it, i + 1);
25396
25397 i = row->used[TEXT_AREA] - (i + 1);
25398 }
25399
25400
25401
25402
25403 if (it->current_x > it->last_visible_x)
25404 {
25405 it->current_x = x_before;
25406 if (!FRAME_WINDOW_P (it->f))
25407 {
25408 for (n = row->used[TEXT_AREA]; i < n; ++i)
25409 {
25410 row->used[TEXT_AREA] = i;
25411 produce_special_glyphs (it, IT_TRUNCATION);
25412 }
25413 }
25414 else
25415 {
25416 row->used[TEXT_AREA] = i;
25417 produce_special_glyphs (it, IT_TRUNCATION);
25418 }
25419 it->hpos = hpos_before;
25420 }
25421 }
25422 else if (IT_OVERFLOW_NEWLINE_INTO_FRINGE (it))
25423 {
25424
25425 if (!get_next_display_element (it))
25426 {
25427 it->continuation_lines_width = 0;
25428 it->font_height = Qnil;
25429 it->voffset = 0;
25430 row->ends_at_zv_p = true;
25431 row->exact_window_width_line_p = true;
25432 break;
25433 }
25434 if (ITERATOR_AT_END_OF_LINE_P (it))
25435 {
25436 row->exact_window_width_line_p = true;
25437 goto at_end_of_line;
25438 }
25439 it->current_x = x_before;
25440 it->hpos = hpos_before;
25441 }
25442
25443 row->truncated_on_right_p = true;
25444 it->continuation_lines_width = 0;
25445 reseat_at_next_visible_line_start (it, false);
25446
25447
25448
25449
25450 if (IT_BYTEPOS (*it) > BEG_BYTE)
25451 row->ends_at_zv_p =
25452 IT_BYTEPOS (*it) >= ZV_BYTE
25453 && (ZV_BYTE <= 1 || FETCH_BYTE (ZV_BYTE - 1) != '\n');
25454 else
25455 row->ends_at_zv_p = false;
25456 break;
25457 }
25458 }
25459
25460 if (wrap_data)
25461 bidi_unshelve_cache (wrap_data, true);
25462
25463
25464
25465 if (it->first_visible_x
25466 && IT_CHARPOS (*it) != CHARPOS (row->start.pos))
25467 {
25468 if (!FRAME_WINDOW_P (it->f)
25469 || (((row->reversed_p
25470 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
25471 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
25472
25473
25474 && row->glyphs[TEXT_AREA]->type != IMAGE_GLYPH))
25475 insert_left_trunc_glyphs (it);
25476 row->truncated_on_left_p = true;
25477 }
25478
25479
25480
25481
25482
25483
25484 row->end = it->current;
25485 if (!it->bidi_p)
25486 {
25487 row->minpos = row->start.pos;
25488 row->maxpos = row->end.pos;
25489 }
25490 else
25491 {
25492
25493
25494
25495
25496 find_row_edges (it, row, min_pos, min_bpos, max_pos, max_bpos);
25497 }
25498
25499
25500
25501
25502
25503 if ((MATRIX_ROW_DISPLAYS_TEXT_P (row) || !overlay_arrow_seen)
25504 && (overlay_arrow_string = overlay_arrow_at_row (it, row),
25505 !NILP (overlay_arrow_string)))
25506 {
25507
25508 if (STRINGP (overlay_arrow_string))
25509 {
25510 struct glyph_row *arrow_row
25511 = get_overlay_arrow_glyph_row (it->w, overlay_arrow_string);
25512 struct glyph *glyph = arrow_row->glyphs[TEXT_AREA];
25513 struct glyph *arrow_end = glyph + arrow_row->used[TEXT_AREA];
25514 struct glyph *p = row->glyphs[TEXT_AREA];
25515 struct glyph *p2, *end;
25516
25517
25518 while (glyph < arrow_end)
25519 *p++ = *glyph++;
25520
25521
25522 p2 = p;
25523 end = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA];
25524 while (p2 < end && CHAR_GLYPH_PADDING_P (*p2))
25525 ++p2;
25526 if (p2 > p)
25527 {
25528 while (p2 < end)
25529 *p++ = *p2++;
25530 row->used[TEXT_AREA] = p2 - row->glyphs[TEXT_AREA];
25531 }
25532 }
25533 else
25534 {
25535 eassert (FIXNUMP (overlay_arrow_string));
25536 row->overlay_arrow_bitmap = XFIXNUM (overlay_arrow_string);
25537 }
25538 overlay_arrow_seen = true;
25539 }
25540
25541
25542 if (!NILP (Vshow_trailing_whitespace))
25543 highlight_trailing_whitespace (it);
25544
25545
25546 compute_line_metrics (it);
25547
25548
25549
25550
25551
25552
25553
25554 row->ends_in_ellipsis_p
25555 = (it->method == GET_FROM_DISPLAY_VECTOR
25556 && it->ellipsis_p);
25557
25558
25559 row->left_user_fringe_bitmap = it->left_user_fringe_bitmap;
25560 row->left_user_fringe_face_id = it->left_user_fringe_face_id;
25561 row->right_user_fringe_bitmap = it->right_user_fringe_bitmap;
25562 row->right_user_fringe_face_id = it->right_user_fringe_face_id;
25563
25564 it->left_user_fringe_bitmap = 0;
25565 it->left_user_fringe_face_id = 0;
25566 it->right_user_fringe_bitmap = 0;
25567 it->right_user_fringe_face_id = 0;
25568
25569
25570
25571
25572
25573
25574 if (MINI_WINDOW_P (it->w) && it->line_wrap == TRUNCATE
25575 && FRAME_WINDOW_P (it->f) && !cursor_in_echo_area)
25576 row->redraw_fringe_bitmaps_p = true;
25577
25578
25579 cvpos = it->w->cursor.vpos;
25580 if ((cvpos < 0
25581
25582
25583
25584
25585
25586
25587
25588
25589 || (it->bidi_p
25590 && !MATRIX_ROW (it->w->desired_matrix, cvpos)->ends_at_zv_p))
25591 && PT >= MATRIX_ROW_START_CHARPOS (row)
25592 && PT <= MATRIX_ROW_END_CHARPOS (row)
25593 && cursor_row_p (row))
25594 set_cursor_from_row (it->w, row, it->w->desired_matrix, 0, 0, 0, 0);
25595
25596
25597
25598
25599
25600 it->current_x = it->hpos = 0;
25601 it->current_y += row->height;
25602
25603
25604 if (hscroll_this_line)
25605 {
25606 it->first_visible_x = first_visible_x;
25607 it->last_visible_x = last_visible_x;
25608 }
25609 SET_TEXT_POS (it->eol_pos, 0, 0);
25610 ++it->vpos;
25611 ++it->glyph_row;
25612
25613
25614
25615
25616 if (it->glyph_row < MATRIX_BOTTOM_TEXT_ROW (it->w->desired_matrix, it->w))
25617 it->glyph_row->reversed_p = row->reversed_p;
25618 it->start = row->end;
25619 return MATRIX_ROW_DISPLAYS_TEXT_P (row);
25620
25621 #undef RECORD_MAX_MIN_POS
25622 }
25623
25624 DEFUN ("current-bidi-paragraph-direction", Fcurrent_bidi_paragraph_direction,
25625 Scurrent_bidi_paragraph_direction, 0, 1, 0,
25626 doc:
25627
25628
25629
25630
25631
25632
25633
25634
25635 )
25636 (Lisp_Object buffer)
25637 {
25638 struct buffer *buf = current_buffer;
25639 struct buffer *old = buf;
25640
25641 if (! NILP (buffer))
25642 {
25643 CHECK_BUFFER (buffer);
25644 buf = XBUFFER (buffer);
25645 }
25646
25647 if (NILP (BVAR (buf, bidi_display_reordering))
25648 || NILP (BVAR (buf, enable_multibyte_characters))
25649
25650
25651 || redisplay__inhibit_bidi)
25652 return Qleft_to_right;
25653 else if (!NILP (BVAR (buf, bidi_paragraph_direction)))
25654 return BVAR (buf, bidi_paragraph_direction);
25655 else
25656 {
25657
25658
25659
25660 struct bidi_it itb;
25661 ptrdiff_t pos = BUF_PT (buf);
25662 ptrdiff_t bytepos = BUF_PT_BYTE (buf);
25663 int c;
25664 void *itb_data = bidi_shelve_cache ();
25665
25666 set_buffer_temp (buf);
25667
25668
25669
25670
25671
25672 if (pos >= ZV && pos > BEGV)
25673 dec_both (&pos, &bytepos);
25674 AUTO_STRING (trailing_white_space, "[\f\t ]*\n");
25675 if (fast_looking_at (trailing_white_space,
25676 pos, bytepos, ZV, ZV_BYTE, Qnil) > 0)
25677 {
25678 while ((c = FETCH_BYTE (bytepos)) == '\n'
25679 || c == ' ' || c == '\t' || c == '\f')
25680 {
25681 if (bytepos <= BEGV_BYTE)
25682 break;
25683 bytepos--;
25684 pos--;
25685 }
25686 while (!CHAR_HEAD_P (FETCH_BYTE (bytepos)))
25687 bytepos--;
25688 }
25689 bidi_init_it (pos, bytepos, FRAME_WINDOW_P (SELECTED_FRAME ()), &itb);
25690 itb.paragraph_dir = NEUTRAL_DIR;
25691 itb.string.s = NULL;
25692 itb.string.lstring = Qnil;
25693 itb.string.bufpos = 0;
25694 itb.string.from_disp_str = false;
25695 itb.string.unibyte = false;
25696
25697
25698
25699 itb.w = NULL;
25700 bidi_paragraph_init (NEUTRAL_DIR, &itb, true);
25701 bidi_unshelve_cache (itb_data, false);
25702 set_buffer_temp (old);
25703 switch (itb.paragraph_dir)
25704 {
25705 case L2R:
25706 return Qleft_to_right;
25707 break;
25708 case R2L:
25709 return Qright_to_left;
25710 break;
25711 default:
25712 emacs_abort ();
25713 }
25714 }
25715 }
25716
25717 DEFUN ("bidi-find-overridden-directionality",
25718 Fbidi_find_overridden_directionality,
25719 Sbidi_find_overridden_directionality, 3, 4, 0,
25720 doc:
25721
25722
25723
25724
25725
25726
25727
25728
25729
25730
25731
25732
25733
25734
25735
25736
25737
25738
25739
25740
25741
25742
25743
25744
25745
25746
25747
25748
25749
25750
25751
25752
25753
25754
25755
25756
25757 )
25758 (Lisp_Object from, Lisp_Object to, Lisp_Object object, Lisp_Object base_dir)
25759 {
25760 struct buffer *buf = current_buffer;
25761 struct buffer *old = buf;
25762 struct window *w = NULL;
25763 bool frame_window_p = FRAME_WINDOW_P (SELECTED_FRAME ());
25764 struct bidi_it itb;
25765 ptrdiff_t from_pos, to_pos, from_bpos;
25766 void *itb_data;
25767
25768 if (!NILP (object))
25769 {
25770 if (BUFFERP (object))
25771 buf = XBUFFER (object);
25772 else if (WINDOWP (object))
25773 {
25774 w = decode_live_window (object);
25775 buf = XBUFFER (w->contents);
25776 frame_window_p = FRAME_WINDOW_P (XFRAME (w->frame));
25777 }
25778 else
25779 CHECK_STRING (object);
25780 }
25781
25782 if (STRINGP (object))
25783 {
25784
25785
25786 if (!STRING_MULTIBYTE (object)
25787
25788
25789
25790 || redisplay__inhibit_bidi)
25791 return Qnil;
25792
25793 validate_subarray (object, from, to, SCHARS (object), &from_pos, &to_pos);
25794 if (from_pos >= SCHARS (object))
25795 return Qnil;
25796
25797
25798 itb_data = bidi_shelve_cache ();
25799 itb.paragraph_dir = NEUTRAL_DIR;
25800 itb.string.lstring = object;
25801 itb.string.s = NULL;
25802 itb.string.schars = SCHARS (object);
25803 itb.string.bufpos = 0;
25804 itb.string.from_disp_str = false;
25805 itb.string.unibyte = false;
25806 itb.w = w;
25807 bidi_init_it (0, 0, frame_window_p, &itb);
25808 }
25809 else
25810 {
25811
25812
25813 if (NILP (BVAR (buf, bidi_display_reordering))
25814 || NILP (BVAR (buf, enable_multibyte_characters))
25815
25816
25817
25818 || redisplay__inhibit_bidi)
25819 return Qnil;
25820
25821 set_buffer_temp (buf);
25822 validate_region (&from, &to);
25823 from_pos = XFIXNUM (from);
25824 to_pos = XFIXNUM (to);
25825 if (from_pos >= ZV)
25826 return Qnil;
25827
25828
25829 itb_data = bidi_shelve_cache ();
25830 from_bpos = CHAR_TO_BYTE (from_pos);
25831 if (from_pos == BEGV)
25832 {
25833 itb.charpos = BEGV;
25834 itb.bytepos = BEGV_BYTE;
25835 }
25836 else if (FETCH_BYTE (from_bpos - 1) == '\n')
25837 {
25838 itb.charpos = from_pos;
25839 itb.bytepos = from_bpos;
25840 }
25841 else
25842 itb.charpos = find_newline_no_quit (from_pos, CHAR_TO_BYTE (from_pos),
25843 -1, &itb.bytepos);
25844 itb.paragraph_dir = NEUTRAL_DIR;
25845 itb.string.s = NULL;
25846 itb.string.lstring = Qnil;
25847 itb.string.bufpos = 0;
25848 itb.string.from_disp_str = false;
25849 itb.string.unibyte = false;
25850 itb.w = w;
25851 bidi_init_it (itb.charpos, itb.bytepos, frame_window_p, &itb);
25852 }
25853
25854 ptrdiff_t found;
25855 bidi_dir_t bdir = EQ (base_dir, Qright_to_left) ? R2L : L2R;
25856 do {
25857 bidi_paragraph_init (bdir, &itb, false);
25858 while ((found = bidi_find_first_overridden (&itb)) < from_pos)
25859 ;
25860 } while (found == ZV && itb.ch == '\n' && itb.charpos < to_pos);
25861
25862 bidi_unshelve_cache (itb_data, false);
25863 set_buffer_temp (old);
25864
25865 return (from_pos <= found && found < to_pos) ? make_fixnum (found) : Qnil;
25866 }
25867
25868 DEFUN ("move-point-visually", Fmove_point_visually,
25869 Smove_point_visually, 1, 1, 0,
25870 doc:
25871
25872
25873
25874 )
25875 (Lisp_Object direction)
25876 {
25877 struct window *w = XWINDOW (selected_window);
25878 struct buffer *b = XBUFFER (w->contents);
25879 struct glyph_row *row;
25880 int dir;
25881 Lisp_Object paragraph_dir;
25882
25883 #define ROW_GLYPH_NEWLINE_P(ROW,GLYPH) \
25884 (!(ROW)->continued_p \
25885 && NILP ((GLYPH)->object) \
25886 && (GLYPH)->type == CHAR_GLYPH \
25887 && (GLYPH)->u.ch == ' ' \
25888 && (GLYPH)->charpos >= 0 \
25889 && !(GLYPH)->avoid_cursor_p)
25890
25891 CHECK_FIXNUM (direction);
25892 dir = XFIXNUM (direction);
25893 if (dir > 0)
25894 dir = 1;
25895 else
25896 dir = -1;
25897
25898
25899
25900
25901 if (w->window_end_valid
25902 && !windows_or_buffers_changed
25903 && b
25904 && !b->clip_changed
25905 && !b->prevent_redisplay_optimizations_p
25906 && !window_outdated (w)
25907
25908
25909
25910 && w->last_point == BUF_PT (b)
25911 && w->cursor.vpos >= 0
25912 && w->cursor.vpos < w->current_matrix->nrows
25913 && (row = MATRIX_ROW (w->current_matrix, w->cursor.vpos))->enabled_p)
25914 {
25915 struct glyph *g = row->glyphs[TEXT_AREA];
25916 struct glyph *e = dir > 0 ? g + row->used[TEXT_AREA] : g - 1;
25917 struct glyph *gpt = g + w->cursor.hpos;
25918
25919 for (g = gpt + dir; (dir > 0 ? g < e : g > e); g += dir)
25920 {
25921 if (BUFFERP (g->object) && g->charpos != PT)
25922 {
25923 SET_PT (g->charpos);
25924 w->cursor.vpos = -1;
25925 return make_fixnum (PT);
25926 }
25927 else if (!NILP (g->object) && !EQ (g->object, gpt->object))
25928 {
25929 ptrdiff_t new_pos;
25930
25931 if (BUFFERP (gpt->object))
25932 {
25933 new_pos = PT;
25934 if ((gpt->resolved_level - row->reversed_p) % 2 == 0)
25935 new_pos += (row->reversed_p ? -dir : dir);
25936 else
25937 new_pos -= (row->reversed_p ? -dir : dir);
25938 new_pos = clip_to_bounds (BEGV, new_pos, ZV);
25939
25940
25941 if (new_pos == PT)
25942 break;
25943 }
25944 else if (BUFFERP (g->object))
25945 new_pos = g->charpos;
25946 else
25947 break;
25948 SET_PT (new_pos);
25949 w->cursor.vpos = -1;
25950 return make_fixnum (PT);
25951 }
25952 else if (ROW_GLYPH_NEWLINE_P (row, g))
25953 {
25954
25955
25956
25957 if (g->charpos > 0)
25958 SET_PT (g->charpos);
25959 else if (row->ends_at_zv_p && PT != ZV)
25960 SET_PT (ZV);
25961 else if (PT != MATRIX_ROW_END_CHARPOS (row) - 1)
25962 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
25963 else
25964 break;
25965 w->cursor.vpos = -1;
25966 return make_fixnum (PT);
25967 }
25968 }
25969 if (g == e || NILP (g->object))
25970 {
25971 if (row->truncated_on_left_p || row->truncated_on_right_p)
25972 goto simulate_display;
25973 if (!row->reversed_p)
25974 row += dir;
25975 else
25976 row -= dir;
25977 if (!(MATRIX_FIRST_TEXT_ROW (w->current_matrix) <= row
25978 && row < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)))
25979 goto simulate_display;
25980
25981 if (dir > 0)
25982 {
25983 if (row->reversed_p && !row->continued_p)
25984 {
25985 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
25986 w->cursor.vpos = -1;
25987 return make_fixnum (PT);
25988 }
25989 g = row->glyphs[TEXT_AREA];
25990 e = g + row->used[TEXT_AREA];
25991 for ( ; g < e; g++)
25992 {
25993 if (BUFFERP (g->object)
25994
25995
25996
25997 || ROW_GLYPH_NEWLINE_P (row, g)
25998
25999
26000 || (row->ends_at_zv_p
26001 && !row->reversed_p
26002 && NILP (g->object)
26003 && g->type == CHAR_GLYPH
26004 && g->u.ch == ' '))
26005 {
26006 if (g->charpos > 0)
26007 SET_PT (g->charpos);
26008 else if (!row->reversed_p
26009 && row->ends_at_zv_p
26010 && PT != ZV)
26011 SET_PT (ZV);
26012 else
26013 continue;
26014 w->cursor.vpos = -1;
26015 return make_fixnum (PT);
26016 }
26017 }
26018 }
26019 else
26020 {
26021 if (!row->reversed_p && !row->continued_p)
26022 {
26023 SET_PT (MATRIX_ROW_END_CHARPOS (row) - 1);
26024 w->cursor.vpos = -1;
26025 return make_fixnum (PT);
26026 }
26027 e = row->glyphs[TEXT_AREA];
26028 g = e + row->used[TEXT_AREA] - 1;
26029 for ( ; g >= e; g--)
26030 {
26031 if (BUFFERP (g->object)
26032 || (ROW_GLYPH_NEWLINE_P (row, g)
26033 && g->charpos > 0)
26034
26035
26036
26037 || g->type == STRETCH_GLYPH
26038 || (row->ends_at_zv_p
26039 && row->reversed_p
26040 && NILP (g->object)
26041 && g->type == CHAR_GLYPH
26042 && g->u.ch == ' '))
26043 {
26044 if (g->charpos > 0)
26045 SET_PT (g->charpos);
26046 else if (row->reversed_p
26047 && row->ends_at_zv_p
26048 && PT != ZV)
26049 SET_PT (ZV);
26050 else
26051 continue;
26052 w->cursor.vpos = -1;
26053 return make_fixnum (PT);
26054 }
26055 }
26056 }
26057 }
26058 }
26059
26060 simulate_display:
26061
26062
26063
26064
26065 if (b)
26066 paragraph_dir = Fcurrent_bidi_paragraph_direction (w->contents);
26067 else
26068 paragraph_dir = Qleft_to_right;
26069 if (EQ (paragraph_dir, Qright_to_left))
26070 dir = -dir;
26071 if (PT <= BEGV && dir < 0)
26072 xsignal0 (Qbeginning_of_buffer);
26073 else if (PT >= ZV && dir > 0)
26074 xsignal0 (Qend_of_buffer);
26075 else
26076 {
26077 struct text_pos pt;
26078 struct it it;
26079 int pt_x, target_x, pixel_width, pt_vpos;
26080 bool at_eol_p;
26081 bool overshoot_expected = false;
26082 bool target_is_eol_p = false;
26083 void *itdata = bidi_shelve_cache ();
26084
26085
26086 SET_TEXT_POS (pt, PT, PT_BYTE);
26087 start_display (&it, w, pt);
26088
26089
26090
26091
26092
26093
26094 if (it.line_wrap == TRUNCATE)
26095 it.last_visible_x = DISP_INFINITY;
26096
26097 if (it.cmp_it.id < 0
26098 && it.method == GET_FROM_STRING
26099 && it.area == TEXT_AREA
26100 && it.string_from_display_prop_p
26101 && (it.sp > 0 && it.stack[it.sp - 1].method == GET_FROM_BUFFER))
26102 overshoot_expected = true;
26103
26104
26105
26106
26107
26108 reseat:
26109 reseat_at_previous_visible_line_start (&it);
26110 it.current_x = it.hpos = it.current_y = it.vpos = 0;
26111 if (IT_CHARPOS (it) != PT)
26112 {
26113 move_it_to (&it, overshoot_expected ? PT - 1 : PT,
26114 -1, -1, -1, MOVE_TO_POS);
26115
26116
26117
26118 if (it.method == GET_FROM_DISPLAY_VECTOR
26119 && it.current.dpvec_index > 0
26120 && !overshoot_expected)
26121 {
26122 overshoot_expected = true;
26123 goto reseat;
26124 }
26125 else if (IT_CHARPOS (it) != PT && !overshoot_expected)
26126 move_it_in_display_line (&it, PT, -1, MOVE_TO_POS);
26127 }
26128 pt_x = it.current_x;
26129 pt_vpos = it.vpos;
26130 if (dir > 0 || overshoot_expected)
26131 {
26132 struct glyph_row *row = it.glyph_row;
26133
26134
26135
26136
26137 if (pt_x == 0)
26138 get_next_display_element (&it);
26139 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26140 it.glyph_row = NULL;
26141 PRODUCE_GLYPHS (&it);
26142 it.glyph_row = row;
26143
26144
26145
26146 it.current_x = pt_x;
26147 }
26148 else
26149 at_eol_p = ITERATOR_AT_END_OF_LINE_P (&it);
26150 pixel_width = it.pixel_width;
26151 if (overshoot_expected && at_eol_p)
26152 pixel_width = 0;
26153 else if (pixel_width <= 0)
26154 pixel_width = 1;
26155
26156
26157
26158
26159 if (overshoot_expected)
26160 {
26161 if (it.bidi_p)
26162 pt_x += pixel_width * it.bidi_it.scan_dir;
26163 else
26164 pt_x += pixel_width;
26165 }
26166
26167
26168
26169
26170
26171
26172
26173 if (dir > 0)
26174 target_x = pt_x + pixel_width;
26175 else
26176 target_x = pt_x - (!FRAME_WINDOW_P (it.f)) * pixel_width;
26177
26178
26179
26180
26181
26182 if (dir < 0)
26183 {
26184 if (pt_x > 0)
26185 {
26186 start_display (&it, w, pt);
26187 if (it.line_wrap == TRUNCATE)
26188 it.last_visible_x = DISP_INFINITY;
26189 reseat_at_previous_visible_line_start (&it);
26190 it.current_x = it.current_y = it.hpos = 0;
26191 if (pt_vpos != 0)
26192 move_it_by_lines (&it, pt_vpos);
26193 }
26194 else
26195 {
26196 move_it_by_lines (&it, -1);
26197 target_x = it.last_visible_x - !FRAME_WINDOW_P (it.f);
26198 target_is_eol_p = true;
26199
26200
26201
26202
26203
26204
26205
26206
26207
26208
26209 if (!FRAME_WINDOW_P (it.f) && it.line_wrap == WORD_WRAP)
26210 {
26211 void *it_data = NULL;
26212 struct it it2;
26213
26214 SAVE_IT (it2, it, it_data);
26215 move_it_in_display_line_to (&it, ZV, target_x,
26216 MOVE_TO_POS | MOVE_TO_X);
26217
26218
26219 if (it.current_x != target_x)
26220 target_x = it.current_x - 1;
26221 RESTORE_IT (&it, &it2, it_data);
26222 }
26223 }
26224 }
26225 else
26226 {
26227 if (at_eol_p
26228 || (target_x >= it.last_visible_x
26229 && it.line_wrap != TRUNCATE))
26230 {
26231 if (pt_x > 0)
26232 move_it_by_lines (&it, 0);
26233 move_it_by_lines (&it, 1);
26234 target_x = 0;
26235 }
26236 }
26237
26238
26239
26240
26241
26242
26243
26244 if (FRAME_WINDOW_P (it.f) && dir < 0)
26245 {
26246 struct text_pos new_pos;
26247 enum move_it_result rc = MOVE_X_REACHED;
26248
26249 if (it.current_x == 0)
26250 get_next_display_element (&it);
26251 if (it.what == IT_COMPOSITION)
26252 {
26253 new_pos.charpos = it.cmp_it.charpos;
26254 new_pos.bytepos = -1;
26255 }
26256 else
26257 new_pos = it.current.pos;
26258
26259 while (it.current_x + it.pixel_width <= target_x
26260 && (rc == MOVE_X_REACHED
26261
26262
26263
26264 || (it.line_wrap == WORD_WRAP
26265 && rc == MOVE_POS_MATCH_OR_ZV)))
26266 {
26267 int new_x = it.current_x + it.pixel_width;
26268
26269
26270
26271
26272
26273
26274
26275 if (it.what == IT_COMPOSITION)
26276 {
26277 new_pos.charpos = it.cmp_it.charpos;
26278 new_pos.bytepos = -1;
26279 }
26280 else
26281 new_pos = it.current.pos;
26282 if (new_x == it.current_x)
26283 new_x++;
26284 rc = move_it_in_display_line_to (&it, ZV, new_x,
26285 MOVE_TO_POS | MOVE_TO_X);
26286 if (ITERATOR_AT_END_OF_LINE_P (&it) && !target_is_eol_p)
26287 break;
26288 }
26289
26290
26291 if (new_pos.bytepos == -1)
26292 new_pos.bytepos = CHAR_TO_BYTE (new_pos.charpos);
26293 it.current.pos = new_pos;
26294 }
26295 else if (it.current_x != target_x)
26296 move_it_in_display_line_to (&it, ZV, target_x, MOVE_TO_POS | MOVE_TO_X);
26297
26298
26299
26300 if (dir > 0)
26301 {
26302 while (IT_CHARPOS (it) == PT)
26303 {
26304 set_iterator_to_next (&it, false);
26305 if (!get_next_display_element (&it))
26306 break;
26307 }
26308 }
26309
26310
26311 SET_PT_BOTH (IT_CHARPOS (it), IT_BYTEPOS (it));
26312 bidi_unshelve_cache (itdata, false);
26313 }
26314
26315 return make_fixnum (PT);
26316
26317 #undef ROW_GLYPH_NEWLINE_P
26318 }
26319
26320 DEFUN ("bidi-resolved-levels", Fbidi_resolved_levels,
26321 Sbidi_resolved_levels, 0, 1, 0,
26322 doc:
26323
26324
26325
26326
26327
26328
26329
26330
26331
26332
26333
26334
26335
26336
26337
26338
26339
26340
26341
26342
26343
26344
26345
26346
26347
26348 )
26349 (Lisp_Object vpos)
26350 {
26351 struct window *w = XWINDOW (selected_window);
26352 struct buffer *b = XBUFFER (w->contents);
26353 int nrow;
26354 struct glyph_row *row;
26355
26356 if (NILP (vpos))
26357 {
26358 int d1, d2, d3, d4, d5;
26359
26360 pos_visible_p (w, PT, &d1, &d2, &d3, &d4, &d5, &nrow);
26361 }
26362 else
26363 {
26364 CHECK_FIXNUM (vpos);
26365 nrow = XFIXNUM (vpos);
26366 }
26367
26368
26369 if (w->window_end_valid
26370 && !windows_or_buffers_changed
26371 && b
26372 && !b->clip_changed
26373 && !b->prevent_redisplay_optimizations_p
26374 && !window_outdated (w)
26375 && nrow >= 0
26376 && nrow < w->current_matrix->nrows
26377 && (row = MATRIX_ROW (w->current_matrix, nrow))->enabled_p
26378 && MATRIX_ROW_DISPLAYS_TEXT_P (row))
26379 {
26380 struct glyph *g, *e, *g1;
26381 int nglyphs, i;
26382 Lisp_Object levels;
26383
26384 if (!row->reversed_p)
26385 {
26386 g = g1 = row->glyphs[TEXT_AREA];
26387 e = g + row->used[TEXT_AREA];
26388
26389
26390
26391 while (g < e
26392 && NILP (g->object)
26393 && g->charpos < 0)
26394 g++;
26395 g1 = g;
26396
26397
26398 for (nglyphs = 0; g < e && !NILP (g->object); g++)
26399 nglyphs++;
26400
26401
26402 levels = make_uninit_vector (nglyphs);
26403 for (i = 0; g1 < g; i++, g1++)
26404 ASET (levels, i, make_fixnum (g1->resolved_level));
26405 }
26406 else
26407 {
26408 g = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
26409 e = row->glyphs[TEXT_AREA] - 1;
26410 while (g > e
26411 && NILP (g->object)
26412 && g->charpos < 0)
26413 g--;
26414 g1 = g;
26415 for (nglyphs = 0; g > e && !NILP (g->object); g--)
26416 nglyphs++;
26417 levels = make_uninit_vector (nglyphs);
26418 for (i = 0; g1 > g; i++, g1--)
26419 ASET (levels, i, make_fixnum (g1->resolved_level));
26420 }
26421 return levels;
26422 }
26423 else
26424 return Qnil;
26425 }
26426
26427
26428
26429
26430
26431
26432
26433
26434
26435
26436
26437
26438
26439
26440
26441
26442
26443 static void
26444 display_menu_bar (struct window *w)
26445 {
26446 struct frame *f = XFRAME (WINDOW_FRAME (w));
26447 struct it it;
26448 Lisp_Object items;
26449 int i;
26450
26451
26452 #ifdef HAVE_NTGUI
26453 if (FRAME_W32_P (f))
26454 return;
26455 #endif
26456 #if defined (HAVE_PGTK)
26457 if (FRAME_PGTK_P (f))
26458 return;
26459 #endif
26460
26461 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26462 if (FRAME_X_P (f))
26463 return;
26464 #endif
26465
26466 #ifdef HAVE_NS
26467 if (FRAME_NS_P (f))
26468 return;
26469 #endif
26470
26471 #ifdef HAVE_HAIKU
26472 if (FRAME_HAIKU_P (f))
26473 return;
26474 #endif
26475
26476 #if defined (USE_X_TOOLKIT) || defined (USE_GTK)
26477 eassert (!FRAME_WINDOW_P (f));
26478 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
26479 it.first_visible_x = 0;
26480 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26481 #elif defined (HAVE_X_WINDOWS)
26482 if (FRAME_WINDOW_P (f))
26483 {
26484
26485
26486 struct window *menu_w;
26487 menu_w = XWINDOW (f->menu_bar_window);
26488 init_iterator (&it, menu_w, -1, -1, menu_w->desired_matrix->rows,
26489 MENU_FACE_ID);
26490 it.first_visible_x = 0;
26491 it.last_visible_x = FRAME_PIXEL_WIDTH (f);
26492 }
26493 else
26494 #endif
26495 {
26496
26497
26498 init_iterator (&it, w, -1, -1, f->desired_matrix->rows,
26499 MENU_FACE_ID);
26500 it.first_visible_x = 0;
26501 it.last_visible_x = FRAME_COLS (f);
26502 }
26503
26504
26505
26506
26507 it.paragraph_embedding = L2R;
26508
26509
26510 for (i = 0; i < FRAME_MENU_BAR_LINES (f); ++i)
26511 {
26512 struct glyph_row *row = it.glyph_row + i;
26513 clear_glyph_row (row);
26514 row->enabled_p = true;
26515 row->full_width_p = true;
26516 row->reversed_p = false;
26517 }
26518
26519
26520 items = FRAME_MENU_BAR_ITEMS (it.f);
26521 for (i = 0; i < ASIZE (items); i += 4)
26522 {
26523 Lisp_Object string;
26524
26525
26526 string = AREF (items, i + 1);
26527 if (NILP (string))
26528 break;
26529
26530
26531 ASET (items, i + 3, make_fixnum (it.hpos));
26532
26533
26534 if (it.current_x < it.last_visible_x)
26535 display_string (NULL, string, Qnil, 0, 0, &it,
26536 SCHARS (string) + 1, 0, 0, STRING_MULTIBYTE (string));
26537 }
26538
26539
26540 if (it.current_x < it.last_visible_x)
26541 display_string ("", Qnil, Qnil, 0, 0, &it, -1, 0, 0, -1);
26542
26543
26544 compute_line_metrics (&it);
26545 }
26546
26547
26548 static void
26549 deep_copy_glyph_row (struct glyph_row *to, struct glyph_row *from)
26550 {
26551 struct glyph *pointers[1 + LAST_AREA];
26552 int to_used = to->used[TEXT_AREA];
26553
26554
26555 memcpy (pointers, to->glyphs, sizeof to->glyphs);
26556
26557
26558 *to = *from;
26559
26560
26561 memcpy (to->glyphs, pointers, sizeof to->glyphs);
26562
26563
26564 memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA],
26565 min (from->used[TEXT_AREA], to_used) * sizeof (struct glyph));
26566
26567
26568
26569 if (to_used > from->used[TEXT_AREA])
26570 fill_up_frame_row_with_spaces (to, to_used);
26571 }
26572
26573
26574
26575
26576
26577
26578
26579
26580
26581
26582
26583
26584
26585
26586
26587
26588
26589
26590
26591
26592
26593
26594 void
26595 display_tty_menu_item (const char *item_text, int width, int face_id,
26596 int x, int y, bool submenu)
26597 {
26598 struct it it;
26599 struct frame *f = SELECTED_FRAME ();
26600 struct window *w = XWINDOW (f->selected_window);
26601 struct glyph_row *row;
26602 size_t item_len = strlen (item_text);
26603
26604 eassert (FRAME_TERMCAP_P (f));
26605
26606
26607
26608
26609
26610
26611 if (y >= f->desired_matrix->nrows)
26612 return;
26613
26614 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
26615 it.first_visible_x = 0;
26616 it.last_visible_x = FRAME_COLS (f) - 1;
26617 row = it.glyph_row;
26618
26619 deep_copy_glyph_row (row, f->current_matrix->rows + y);
26620 bool saved_width = row->full_width_p;
26621 row->full_width_p = true;
26622 bool saved_reversed = row->reversed_p;
26623 row->reversed_p = false;
26624 row->enabled_p = true;
26625
26626
26627
26628 eassert (x < f->desired_matrix->matrix_w);
26629 it.current_x = it.hpos = x;
26630 it.current_y = it.vpos = y;
26631 int saved_used = row->used[TEXT_AREA];
26632 bool saved_truncated = row->truncated_on_right_p;
26633 row->used[TEXT_AREA] = x;
26634 it.face_id = face_id;
26635 it.line_wrap = TRUNCATE;
26636
26637
26638
26639
26640
26641
26642 it.paragraph_embedding = L2R;
26643
26644
26645 display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, FRAME_COLS (f) - 1, -1);
26646 width--;
26647
26648 if (submenu)
26649 {
26650 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26651 item_len, 0, FRAME_COLS (f) - 1, -1);
26652 width -= item_len;
26653
26654 display_string (" >", Qnil, Qnil, 0, 0, &it, width, 0,
26655 FRAME_COLS (f) - 1, -1);
26656 }
26657 else
26658 display_string (item_text, Qnil, Qnil, 0, 0, &it,
26659 width, 0, FRAME_COLS (f) - 1, -1);
26660
26661 row->used[TEXT_AREA] = max (saved_used, row->used[TEXT_AREA]);
26662 row->truncated_on_right_p = saved_truncated;
26663 row->hash = row_hash (row);
26664 row->full_width_p = saved_width;
26665 row->reversed_p = saved_reversed;
26666 }
26667
26668
26669
26670
26671
26672
26673
26674
26675
26676
26677 static int
26678 redisplay_mode_lines (Lisp_Object window, bool force)
26679 {
26680 int nwindows = 0;
26681
26682 while (!NILP (window))
26683 {
26684 struct window *w = XWINDOW (window);
26685
26686 if (WINDOWP (w->contents))
26687 nwindows += redisplay_mode_lines (w->contents, force);
26688 else if (force
26689 || FRAME_GARBAGED_P (XFRAME (w->frame))
26690 || !MATRIX_MODE_LINE_ROW (w->current_matrix)->enabled_p)
26691 {
26692 struct text_pos lpoint;
26693 struct buffer *old = current_buffer;
26694
26695
26696 SET_TEXT_POS (lpoint, PT, PT_BYTE);
26697 set_buffer_internal_1 (XBUFFER (w->contents));
26698
26699
26700
26701 if (!EQ (window, selected_window))
26702 {
26703 struct text_pos pt;
26704
26705 CLIP_TEXT_POS_FROM_MARKER (pt, w->pointm);
26706 TEMP_SET_PT_BOTH (CHARPOS (pt), BYTEPOS (pt));
26707 }
26708
26709
26710 clear_glyph_matrix (w->desired_matrix);
26711 if (display_mode_lines (w))
26712 ++nwindows;
26713
26714
26715 set_buffer_internal_1 (old);
26716 TEMP_SET_PT_BOTH (CHARPOS (lpoint), BYTEPOS (lpoint));
26717 }
26718
26719 window = w->next;
26720 }
26721
26722 return nwindows;
26723 }
26724
26725
26726
26727
26728
26729
26730 static int
26731 display_mode_lines (struct window *w)
26732 {
26733 Lisp_Object old_selected_window = selected_window;
26734 Lisp_Object new_frame = w->frame;
26735 specpdl_ref count = SPECPDL_INDEX ();
26736 int n = 0;
26737
26738 record_unwind_protect (restore_selected_window, selected_window);
26739 record_unwind_protect
26740 (restore_frame_selected_window, XFRAME (new_frame)->selected_window);
26741
26742 if (window_wants_mode_line (w))
26743 {
26744 Lisp_Object window;
26745 Lisp_Object default_help
26746 = buffer_local_value (Qmode_line_default_help_echo, w->contents);
26747
26748
26749
26750 XSETWINDOW (window, w);
26751 if (FUNCTIONP (default_help))
26752 wset_mode_line_help_echo (w, safe_call1 (default_help, window));
26753 else if (STRINGP (default_help))
26754 wset_mode_line_help_echo (w, default_help);
26755 else
26756 wset_mode_line_help_echo (w, Qnil);
26757 }
26758
26759 selected_frame = new_frame;
26760
26761
26762 XSETWINDOW (selected_window, w);
26763 XFRAME (new_frame)->selected_window = selected_window;
26764
26765
26766 line_number_displayed = false;
26767 w->column_number_displayed = -1;
26768
26769 if (window_wants_mode_line (w))
26770 {
26771 Lisp_Object window_mode_line_format
26772 = window_parameter (w, Qmode_line_format);
26773 struct window *sel_w = XWINDOW (old_selected_window);
26774
26775
26776 display_mode_line (w,
26777 CURRENT_MODE_LINE_ACTIVE_FACE_ID_3 (sel_w, sel_w, w),
26778 NILP (window_mode_line_format)
26779 ? BVAR (current_buffer, mode_line_format)
26780 : window_mode_line_format);
26781 ++n;
26782 }
26783
26784 if (window_wants_tab_line (w))
26785 {
26786 Lisp_Object window_tab_line_format
26787 = window_parameter (w, Qtab_line_format);
26788
26789 display_mode_line (w, TAB_LINE_FACE_ID,
26790 NILP (window_tab_line_format)
26791 ? BVAR (current_buffer, tab_line_format)
26792 : window_tab_line_format);
26793 ++n;
26794 }
26795
26796 if (window_wants_header_line (w))
26797 {
26798 Lisp_Object window_header_line_format
26799 = window_parameter (w, Qheader_line_format);
26800
26801 display_mode_line (w, HEADER_LINE_FACE_ID,
26802 NILP (window_header_line_format)
26803 ? BVAR (current_buffer, header_line_format)
26804 : window_header_line_format);
26805 ++n;
26806 }
26807
26808 unbind_to (count, Qnil);
26809
26810 if (n > 0)
26811 w->must_be_updated_p = true;
26812 return n;
26813 }
26814
26815
26816
26817
26818
26819
26820
26821
26822 static int
26823 display_mode_line (struct window *w, enum face_id face_id, Lisp_Object format)
26824 {
26825 struct it it;
26826 struct face *face;
26827 specpdl_ref count = SPECPDL_INDEX ();
26828
26829 init_iterator (&it, w, -1, -1, NULL, face_id);
26830
26831
26832 it.glyph_row->enabled_p = false;
26833 prepare_desired_row (w, it.glyph_row, true);
26834
26835 it.glyph_row->mode_line_p = true;
26836 if (face_id == TAB_LINE_FACE_ID)
26837 {
26838 it.glyph_row->tab_line_p = true;
26839 w->desired_matrix->tab_line_p = true;
26840 }
26841 else if (face_id == HEADER_LINE_FACE_ID)
26842 w->desired_matrix->header_line_p = true;
26843
26844
26845
26846
26847 it.paragraph_embedding = L2R;
26848
26849 record_unwind_protect (unwind_format_mode_line,
26850 format_mode_line_unwind_data (NULL, NULL,
26851 Qnil, false));
26852
26853
26854
26855
26856 push_kboard (FRAME_KBOARD (it.f));
26857 record_unwind_save_match_data ();
26858
26859 if (NILP (Vmode_line_compact)
26860 || face_id == HEADER_LINE_FACE_ID || face_id == TAB_LINE_FACE_ID)
26861 {
26862 mode_line_target = MODE_LINE_DISPLAY;
26863 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
26864 }
26865 else
26866 {
26867 Lisp_Object mode_string = Fformat_mode_line (format, Qnil, Qnil, Qnil);
26868 if (EQ (Vmode_line_compact, Qlong)
26869 && WINDOW_TOTAL_COLS (w) >= SCHARS (mode_string))
26870 {
26871
26872
26873 display_string (NULL, mode_string, Qnil,
26874 0, 0, &it, 0, 0, 0,
26875 STRING_MULTIBYTE (mode_string));
26876 }
26877 else
26878 {
26879
26880 ptrdiff_t i = 0, i_byte = 0, start = 0;
26881 int prev = 0;
26882
26883 while (i < SCHARS (mode_string))
26884 {
26885 int c = fetch_string_char_advance (mode_string, &i, &i_byte);
26886 if (c == ' ' && prev == ' ')
26887 {
26888 display_string (NULL,
26889 Fsubstring (mode_string, make_fixnum (start),
26890 make_fixnum (i - 1)),
26891 Qnil, 0, 0, &it, 0, 0, 0,
26892 STRING_MULTIBYTE (mode_string));
26893
26894 while (c == ' ' && i < SCHARS (mode_string))
26895 c = fetch_string_char_advance (mode_string, &i, &i_byte);
26896 start = i - 1;
26897 }
26898 prev = c;
26899 }
26900
26901
26902 if (start < i)
26903 display_string (NULL,
26904 Fsubstring (mode_string, make_fixnum (start),
26905 make_fixnum (i)),
26906 Qnil, 0, 0, &it, 0, 0, 0,
26907 STRING_MULTIBYTE (mode_string));
26908 }
26909 }
26910 pop_kboard ();
26911
26912 unbind_to (count, Qnil);
26913
26914
26915 display_string (" ", Qnil, Qnil, 0, 0, &it, 10000, -1, -1, 0);
26916
26917 compute_line_metrics (&it);
26918 it.glyph_row->full_width_p = true;
26919 it.glyph_row->continued_p = false;
26920 it.glyph_row->truncated_on_left_p = false;
26921 it.glyph_row->truncated_on_right_p = false;
26922
26923
26924 face = FACE_FROM_ID (it.f, face_id);
26925 extend_face_to_end_of_line (&it);
26926 if (face->box != FACE_NO_BOX)
26927 {
26928 struct glyph *last = (it.glyph_row->glyphs[TEXT_AREA]
26929 + it.glyph_row->used[TEXT_AREA] - 1);
26930 int box_thickness = face->box_vertical_line_width;
26931 last->right_box_line_p = true;
26932
26933
26934
26935
26936
26937
26938 if (box_thickness > 0)
26939 last->pixel_width += max (0, (box_thickness
26940 - (it.current_x - it.last_visible_x)));
26941 }
26942
26943 return it.glyph_row->height;
26944 }
26945
26946
26947
26948
26949 static Lisp_Object
26950 move_elt_to_front (Lisp_Object elt, Lisp_Object list)
26951 {
26952 register Lisp_Object tail, prev;
26953 register Lisp_Object tem;
26954
26955 tail = list;
26956 prev = Qnil;
26957 while (CONSP (tail))
26958 {
26959 tem = XCAR (tail);
26960
26961 if (EQ (elt, tem))
26962 {
26963
26964 if (NILP (prev))
26965 list = XCDR (tail);
26966 else
26967 Fsetcdr (prev, XCDR (tail));
26968
26969
26970 Fsetcdr (tail, list);
26971 return tail;
26972 }
26973 else
26974 prev = tail;
26975 tail = XCDR (tail);
26976 maybe_quit ();
26977 }
26978
26979
26980 return list;
26981 }
26982
26983
26984
26985
26986
26987 static Lisp_Object
26988 safe_set_text_properties (ptrdiff_t nargs, Lisp_Object *args)
26989 {
26990 eassert (nargs == 4);
26991 return Fset_text_properties (args[0], args[1], args[2], args[3]);
26992 }
26993
26994
26995
26996
26997
26998
26999
27000
27001
27002
27003
27004
27005
27006
27007
27008
27009
27010
27011
27012
27013
27014
27015
27016
27017
27018 static int
27019 display_mode_element (struct it *it, int depth, int field_width, int precision,
27020 Lisp_Object elt, Lisp_Object props, bool risky)
27021 {
27022 int n = 0, field, prec;
27023 bool literal = false;
27024
27025 tail_recurse:
27026 if (depth > 100)
27027 elt = build_string ("*too-deep*");
27028
27029 depth++;
27030
27031 switch (XTYPE (elt))
27032 {
27033 case Lisp_String:
27034 {
27035
27036 unsigned char c;
27037 ptrdiff_t offset = 0;
27038
27039 if (SCHARS (elt) > 0
27040 && (!NILP (props) || risky))
27041 {
27042 Lisp_Object oprops, aelt;
27043 oprops = Ftext_properties_at (make_fixnum (0), elt);
27044
27045
27046
27047
27048
27049 if (NILP (Fequal (props, oprops)) || risky)
27050 {
27051
27052
27053 if (! NILP (oprops) && !risky)
27054 {
27055 Lisp_Object tem;
27056
27057 oprops = Fcopy_sequence (oprops);
27058 tem = props;
27059 while (CONSP (tem))
27060 {
27061 oprops = plist_put (oprops, XCAR (tem),
27062 XCAR (XCDR (tem)));
27063 tem = XCDR (XCDR (tem));
27064 }
27065 props = oprops;
27066 }
27067
27068 aelt = Fassoc (elt, mode_line_proptrans_alist, Qnil);
27069 if (! NILP (aelt) && !NILP (Fequal (props, XCDR (aelt))))
27070 {
27071
27072
27073 elt = XCAR (aelt);
27074 mode_line_proptrans_alist
27075 = move_elt_to_front (aelt, mode_line_proptrans_alist);
27076 }
27077 else
27078 {
27079 Lisp_Object tem;
27080
27081
27082
27083 if (! NILP (aelt))
27084 mode_line_proptrans_alist
27085 = Fdelq (aelt, mode_line_proptrans_alist);
27086
27087 elt = Fcopy_sequence (elt);
27088
27089
27090
27091 internal_condition_case_n (safe_set_text_properties,
27092 4,
27093 ((Lisp_Object [])
27094 {make_fixnum (0),
27095 Flength (elt),
27096 props,
27097 elt}),
27098 Qt, safe_eval_handler);
27099
27100 mode_line_proptrans_alist
27101 = Fcons (Fcons (elt, props),
27102 mode_line_proptrans_alist);
27103
27104
27105 tem = Fnthcdr (make_fixnum (50),
27106 mode_line_proptrans_alist);
27107 if (! NILP (tem))
27108 XSETCDR (tem, Qnil);
27109 }
27110 }
27111 }
27112
27113 offset = 0;
27114
27115 if (literal)
27116 {
27117 prec = precision - n;
27118 switch (mode_line_target)
27119 {
27120 case MODE_LINE_NOPROP:
27121 case MODE_LINE_TITLE:
27122 n += store_mode_line_noprop (SSDATA (elt), -1, prec);
27123 break;
27124 case MODE_LINE_STRING:
27125 n += store_mode_line_string (NULL, elt, true, 0, prec, Qnil);
27126 break;
27127 case MODE_LINE_DISPLAY:
27128 n += display_string (NULL, elt, Qnil, 0, 0, it,
27129 0, prec, 0, STRING_MULTIBYTE (elt));
27130 break;
27131 }
27132
27133 break;
27134 }
27135
27136
27137
27138 while ((precision <= 0 || n < precision)
27139 && SREF (elt, offset) != 0
27140 && (mode_line_target != MODE_LINE_DISPLAY
27141 || it->current_x < it->last_visible_x))
27142 {
27143 ptrdiff_t last_offset = offset;
27144
27145
27146 while ((c = SREF (elt, offset++)) != '\0' && c != '%')
27147 ;
27148
27149 if (offset - 1 != last_offset)
27150 {
27151 ptrdiff_t nchars, nbytes;
27152
27153
27154
27155
27156 offset--;
27157
27158 prec = c_string_width (SDATA (elt) + last_offset,
27159 offset - last_offset, precision - n,
27160 &nchars, &nbytes);
27161
27162 switch (mode_line_target)
27163 {
27164 case MODE_LINE_NOPROP:
27165 case MODE_LINE_TITLE:
27166 n += store_mode_line_noprop (SSDATA (elt) + last_offset, 0, prec);
27167 break;
27168 case MODE_LINE_STRING:
27169 {
27170 ptrdiff_t bytepos = last_offset;
27171 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27172 ptrdiff_t endpos = (precision <= 0
27173 ? string_byte_to_char (elt, offset)
27174 : charpos + nchars);
27175 Lisp_Object mode_string
27176 = Fsubstring (elt, make_fixnum (charpos),
27177 make_fixnum (endpos));
27178 n += store_mode_line_string (NULL, mode_string, false,
27179 0, 0, Qnil);
27180 }
27181 break;
27182 case MODE_LINE_DISPLAY:
27183 {
27184 ptrdiff_t bytepos = last_offset;
27185 ptrdiff_t charpos = string_byte_to_char (elt, bytepos);
27186
27187 if (precision <= 0)
27188 nchars = string_byte_to_char (elt, offset) - charpos;
27189 n += display_string (NULL, elt, Qnil, 0, charpos,
27190 it, 0, nchars, 0,
27191 STRING_MULTIBYTE (elt));
27192 }
27193 break;
27194 }
27195 }
27196 else
27197 {
27198 ptrdiff_t percent_position = offset;
27199
27200
27201
27202 field = 0;
27203 while ((c = SREF (elt, offset++)) >= '0' && c <= '9')
27204 field = field * 10 + c - '0';
27205
27206
27207 if (field_width - n > 0 && field > field_width - n)
27208 field = field_width - n;
27209
27210
27211 prec = precision - n;
27212
27213 if (c == 'M')
27214 n += display_mode_element (it, depth, field, prec,
27215 Vglobal_mode_string, props,
27216 risky);
27217 else if (c != 0)
27218 {
27219 bool multibyte;
27220 ptrdiff_t bytepos, charpos;
27221 const char *spec;
27222 Lisp_Object string;
27223
27224 bytepos = percent_position;
27225 charpos = (STRING_MULTIBYTE (elt)
27226 ? string_byte_to_char (elt, bytepos)
27227 : bytepos);
27228 spec = decode_mode_spec (it->w, c, field, &string);
27229 eassert (NILP (string) || STRINGP (string));
27230 multibyte = !NILP (string) && STRING_MULTIBYTE (string);
27231
27232
27233 ptrdiff_t nbytes = strlen (spec);
27234 ptrdiff_t nchars, mb_nbytes;
27235 parse_str_as_multibyte ((const unsigned char *)spec, nbytes,
27236 &nchars, &mb_nbytes);
27237 if (!(nbytes == nchars || nbytes != mb_nbytes))
27238 multibyte = true;
27239
27240 switch (mode_line_target)
27241 {
27242 case MODE_LINE_NOPROP:
27243 case MODE_LINE_TITLE:
27244 n += store_mode_line_noprop (spec, field, prec);
27245 break;
27246 case MODE_LINE_STRING:
27247 {
27248 Lisp_Object tem = build_string (spec);
27249 props = Ftext_properties_at (make_fixnum (charpos), elt);
27250
27251 n += store_mode_line_string (NULL, tem, false,
27252 field, prec, props);
27253 }
27254 break;
27255 case MODE_LINE_DISPLAY:
27256 {
27257 int nglyphs_before, nwritten;
27258
27259 nglyphs_before = it->glyph_row->used[TEXT_AREA];
27260 nwritten = display_string (spec, string, elt,
27261 charpos, 0, it,
27262 field, prec, 0,
27263 multibyte);
27264
27265
27266
27267
27268 if (nwritten > 0)
27269 {
27270 struct glyph *glyph
27271 = (it->glyph_row->glyphs[TEXT_AREA]
27272 + nglyphs_before);
27273 int i;
27274
27275 for (i = 0; i < nwritten; ++i)
27276 {
27277 glyph[i].object = elt;
27278 glyph[i].charpos = charpos;
27279 }
27280
27281 n += nwritten;
27282 }
27283 }
27284 break;
27285 }
27286 }
27287 else
27288 break;
27289 }
27290 }
27291 }
27292 break;
27293
27294 case Lisp_Symbol:
27295
27296
27297
27298
27299 {
27300 register Lisp_Object tem;
27301
27302
27303
27304 if (NILP (Fget (elt, Qrisky_local_variable)))
27305 risky = true;
27306
27307 tem = Fboundp (elt);
27308 if (!NILP (tem))
27309 {
27310 tem = Fsymbol_value (elt);
27311
27312
27313 if (STRINGP (tem))
27314 literal = true;
27315
27316 if (!EQ (tem, elt))
27317 {
27318
27319 elt = tem;
27320 goto tail_recurse;
27321 }
27322 }
27323 }
27324 break;
27325
27326 case Lisp_Cons:
27327 {
27328 register Lisp_Object car, tem;
27329
27330
27331
27332
27333
27334
27335
27336
27337
27338
27339 car = XCAR (elt);
27340 if (EQ (car, QCeval))
27341 {
27342
27343
27344
27345 if (risky)
27346 break;
27347
27348 if (CONSP (XCDR (elt)))
27349 {
27350 Lisp_Object spec;
27351 spec = safe__eval (true, XCAR (XCDR (elt)));
27352
27353
27354
27355
27356
27357
27358 if (!FRAME_LIVE_P (it->f))
27359 signal_error (":eval deleted the frame being displayed", elt);
27360 n += display_mode_element (it, depth, field_width - n,
27361 precision - n, spec, props,
27362 risky);
27363 }
27364 }
27365 else if (EQ (car, QCpropertize))
27366 {
27367
27368
27369
27370 if (risky)
27371 break;
27372
27373 if (CONSP (XCDR (elt)))
27374 n += display_mode_element (it, depth, field_width - n,
27375 precision - n, XCAR (XCDR (elt)),
27376 XCDR (XCDR (elt)), risky);
27377 }
27378 else if (SYMBOLP (car))
27379 {
27380 tem = Fboundp (car);
27381 elt = XCDR (elt);
27382 if (!CONSP (elt))
27383 goto invalid;
27384
27385
27386 if (!NILP (tem))
27387 {
27388 tem = Fsymbol_value (car);
27389 if (!NILP (tem))
27390 {
27391 elt = XCAR (elt);
27392 goto tail_recurse;
27393 }
27394 }
27395
27396
27397
27398 elt = XCDR (elt);
27399 if (NILP (elt))
27400 break;
27401 else if (!CONSP (elt))
27402 goto invalid;
27403 elt = XCAR (elt);
27404 goto tail_recurse;
27405 }
27406 else if (FIXNUMP (car))
27407 {
27408 register int lim = XFIXNUM (car);
27409 elt = XCDR (elt);
27410 if (lim < 0)
27411 {
27412
27413 if (precision <= 0)
27414 precision = -lim;
27415 else
27416 precision = min (precision, -lim);
27417 }
27418 else if (lim > 0)
27419 {
27420
27421
27422 if (precision > 0)
27423 lim = min (precision, lim);
27424
27425
27426
27427
27428 field_width = max (lim, field_width);
27429 }
27430 goto tail_recurse;
27431 }
27432 else if (STRINGP (car) || CONSP (car))
27433 FOR_EACH_TAIL_SAFE (elt)
27434 {
27435 if (0 < precision && precision <= n)
27436 break;
27437 n += display_mode_element (it, depth,
27438
27439
27440 (! CONSP (XCDR (elt))
27441 ? field_width - n
27442 : 0),
27443 precision - n, XCAR (elt),
27444 props, risky);
27445 }
27446 }
27447 break;
27448
27449 default:
27450 invalid:
27451 elt = build_string ("*invalid*");
27452 goto tail_recurse;
27453 }
27454
27455
27456 if (field_width > 0 && n < field_width)
27457 {
27458 switch (mode_line_target)
27459 {
27460 case MODE_LINE_NOPROP:
27461 case MODE_LINE_TITLE:
27462 n += store_mode_line_noprop ("", field_width - n, 0);
27463 break;
27464 case MODE_LINE_STRING:
27465 n += store_mode_line_string ("", Qnil, false, field_width - n, 0,
27466 Qnil);
27467 break;
27468 case MODE_LINE_DISPLAY:
27469 n += display_string ("", Qnil, Qnil, 0, 0, it, field_width - n,
27470 0, 0, 0);
27471 break;
27472 }
27473 }
27474
27475 return n;
27476 }
27477
27478
27479
27480
27481
27482
27483
27484
27485
27486
27487
27488
27489
27490
27491
27492
27493
27494
27495
27496
27497 static int
27498 store_mode_line_string (const char *string, Lisp_Object lisp_string,
27499 bool copy_string,
27500 int field_width, int precision, Lisp_Object props)
27501 {
27502 ptrdiff_t len;
27503 int n = 0;
27504
27505 if (string != NULL)
27506 {
27507 len = strnlen (string, precision <= 0 ? SIZE_MAX : precision);
27508 lisp_string = make_string (string, len);
27509 if (NILP (props))
27510 props = mode_line_string_face_prop;
27511 else if (!NILP (mode_line_string_face))
27512 {
27513 Lisp_Object face = plist_get (props, Qface);
27514 props = Fcopy_sequence (props);
27515 if (NILP (face))
27516 face = mode_line_string_face;
27517 else
27518 face = list2 (face, mode_line_string_face);
27519 props = plist_put (props, Qface, face);
27520 }
27521 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27522 props, lisp_string);
27523 }
27524 else
27525 {
27526 len = SCHARS (lisp_string);
27527 if (precision > 0 && len > precision)
27528 {
27529 len = precision;
27530 lisp_string = Fsubstring (lisp_string, make_fixnum (0), make_fixnum (len));
27531 precision = -1;
27532 }
27533 if (!NILP (mode_line_string_face))
27534 {
27535 Lisp_Object face;
27536 if (NILP (props))
27537 props = Ftext_properties_at (make_fixnum (0), lisp_string);
27538 face = plist_get (props, Qface);
27539 if (NILP (face))
27540 face = mode_line_string_face;
27541 else
27542 face = list2 (face, mode_line_string_face);
27543 props = list2 (Qface, face);
27544 if (copy_string)
27545 lisp_string = Fcopy_sequence (lisp_string);
27546 }
27547 if (!NILP (props))
27548 Fadd_text_properties (make_fixnum (0), make_fixnum (len),
27549 props, lisp_string);
27550 }
27551
27552 if (len > 0)
27553 {
27554 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27555 n += len;
27556 }
27557
27558 if (field_width > len)
27559 {
27560 field_width -= len;
27561 lisp_string = Fmake_string (make_fixnum (field_width), make_fixnum (' '),
27562 Qnil);
27563 if (!NILP (props))
27564 Fadd_text_properties (make_fixnum (0), make_fixnum (field_width),
27565 props, lisp_string);
27566 mode_line_string_list = Fcons (lisp_string, mode_line_string_list);
27567 n += field_width;
27568 }
27569
27570 return n;
27571 }
27572
27573
27574 DEFUN ("format-mode-line", Fformat_mode_line, Sformat_mode_line,
27575 1, 4, 0,
27576 doc:
27577
27578
27579
27580
27581
27582
27583
27584
27585
27586
27587
27588
27589
27590
27591
27592 )
27593 (Lisp_Object format, Lisp_Object face,
27594 Lisp_Object window, Lisp_Object buffer)
27595 {
27596 struct it it;
27597 int len;
27598 struct window *w;
27599 struct buffer *old_buffer = NULL;
27600 int face_id;
27601 bool no_props = FIXNUMP (face);
27602 specpdl_ref count = SPECPDL_INDEX ();
27603 Lisp_Object str;
27604 int string_start = 0;
27605
27606 w = decode_any_window (window);
27607 XSETWINDOW (window, w);
27608
27609 if (NILP (buffer))
27610 buffer = w->contents;
27611 CHECK_BUFFER (buffer);
27612
27613
27614
27615 if (NILP (format) || noninteractive)
27616 return empty_unibyte_string;
27617
27618 if (no_props)
27619 face = Qnil;
27620
27621 face_id = (NILP (face) || EQ (face, Qdefault)) ? DEFAULT_FACE_ID
27622 : EQ (face, Qt) ? (EQ (window, selected_window)
27623 ? MODE_LINE_ACTIVE_FACE_ID : MODE_LINE_INACTIVE_FACE_ID)
27624 : EQ (face, Qmode_line_active) ? MODE_LINE_ACTIVE_FACE_ID
27625 : EQ (face, Qmode_line_inactive) ? MODE_LINE_INACTIVE_FACE_ID
27626 : EQ (face, Qheader_line) ? HEADER_LINE_FACE_ID
27627 : EQ (face, Qtab_line) ? TAB_LINE_FACE_ID
27628 : EQ (face, Qtab_bar) ? TAB_BAR_FACE_ID
27629 : EQ (face, Qtool_bar) ? TOOL_BAR_FACE_ID
27630 : DEFAULT_FACE_ID;
27631
27632 old_buffer = current_buffer;
27633
27634
27635
27636 record_unwind_protect (unwind_format_mode_line,
27637 format_mode_line_unwind_data
27638 (XFRAME (WINDOW_FRAME (w)),
27639 old_buffer, selected_window, true));
27640 mode_line_proptrans_alist = Qnil;
27641
27642 Fselect_window (window, Qt);
27643 set_buffer_internal_1 (XBUFFER (buffer));
27644
27645 init_iterator (&it, w, -1, -1, NULL, face_id);
27646
27647 if (no_props)
27648 {
27649 mode_line_target = MODE_LINE_NOPROP;
27650 mode_line_string_face_prop = Qnil;
27651 mode_line_string_list = Qnil;
27652 string_start = MODE_LINE_NOPROP_LEN (0);
27653 }
27654 else
27655 {
27656 mode_line_target = MODE_LINE_STRING;
27657 mode_line_string_list = Qnil;
27658 mode_line_string_face = face;
27659 mode_line_string_face_prop
27660 = NILP (face) ? Qnil : list2 (Qface, face);
27661 }
27662
27663 push_kboard (FRAME_KBOARD (it.f));
27664 display_mode_element (&it, 0, 0, 0, format, Qnil, false);
27665 pop_kboard ();
27666
27667 if (no_props)
27668 {
27669 len = MODE_LINE_NOPROP_LEN (string_start);
27670 str = make_string (mode_line_noprop_buf + string_start, len);
27671 }
27672 else
27673 {
27674 mode_line_string_list = Fnreverse (mode_line_string_list);
27675 str = Fmapconcat (Qidentity, mode_line_string_list,
27676 empty_unibyte_string);
27677 }
27678
27679 return unbind_to (count, str);
27680 }
27681
27682
27683
27684
27685 static void
27686 pint2str (register char *buf, register int width, register ptrdiff_t d)
27687 {
27688 register char *p = buf;
27689
27690 if (d <= 0)
27691 *p++ = '0';
27692 else
27693 {
27694 while (d > 0)
27695 {
27696 *p++ = d % 10 + '0';
27697 d /= 10;
27698 }
27699 }
27700
27701 for (width -= (int) (p - buf); width > 0; --width)
27702 *p++ = ' ';
27703 *p-- = '\0';
27704 while (p > buf)
27705 {
27706 d = *buf;
27707 *buf++ = *p;
27708 *p-- = d;
27709 }
27710 }
27711
27712
27713
27714
27715
27716 static const char power_letter[] =
27717 {
27718 0,
27719 'k',
27720 'M',
27721 'G',
27722 'T',
27723 'P',
27724 'E',
27725 'Z',
27726 'Y'
27727 };
27728
27729 static void
27730 pint2hrstr (char *buf, int width, ptrdiff_t d)
27731 {
27732
27733
27734 ptrdiff_t quotient = d;
27735 int remainder = 0;
27736
27737 int tenths = -1;
27738 int exponent = 0;
27739
27740
27741 int length;
27742
27743 char * psuffix;
27744 char * p;
27745
27746 if (quotient >= 1000)
27747 {
27748
27749 do
27750 {
27751 remainder = quotient % 1000;
27752 quotient /= 1000;
27753 exponent++;
27754 }
27755 while (quotient >= 1000);
27756
27757
27758 if (quotient <= 9)
27759 {
27760 tenths = remainder / 100;
27761 if (remainder % 100 >= 50)
27762 {
27763 if (tenths < 9)
27764 tenths++;
27765 else
27766 {
27767 quotient++;
27768 if (quotient == 10)
27769 tenths = -1;
27770 else
27771 tenths = 0;
27772 }
27773 }
27774 }
27775 else
27776 if (remainder >= 500)
27777 {
27778 if (quotient < 999)
27779 quotient++;
27780 else
27781 {
27782 quotient = 1;
27783 exponent++;
27784 tenths = 0;
27785 }
27786 }
27787 }
27788
27789
27790 if (tenths == -1 && quotient <= 99)
27791 if (quotient <= 9)
27792 length = 1;
27793 else
27794 length = 2;
27795 else
27796 length = 3;
27797 p = psuffix = buf + max (width, length);
27798
27799
27800 *psuffix++ = power_letter[exponent];
27801 *psuffix = '\0';
27802
27803
27804 if (tenths >= 0)
27805 {
27806 *--p = '0' + tenths;
27807 *--p = '.';
27808 }
27809
27810
27811 do
27812 {
27813 int digit = quotient % 10;
27814 *--p = '0' + digit;
27815 }
27816 while ((quotient /= 10) != 0);
27817
27818
27819 while (buf < p)
27820 *--p = ' ';
27821 }
27822
27823
27824
27825
27826
27827 static unsigned char invalid_eol_type[] = "(*invalid*)";
27828
27829 static char *
27830 decode_mode_spec_coding (Lisp_Object coding_system, char *buf, bool eol_flag)
27831 {
27832 Lisp_Object val;
27833 bool multibyte = !NILP (BVAR (current_buffer, enable_multibyte_characters));
27834 const unsigned char *eol_str;
27835 int eol_str_len;
27836
27837 Lisp_Object eoltype;
27838
27839 val = CODING_SYSTEM_SPEC (coding_system);
27840 eoltype = Qnil;
27841
27842 if (!VECTORP (val))
27843 {
27844 *buf++ = multibyte ? '-' : ' ';
27845 if (eol_flag)
27846 eoltype = eol_mnemonic_undecided;
27847
27848 }
27849 else
27850 {
27851 Lisp_Object attrs;
27852 Lisp_Object eolvalue;
27853
27854 attrs = AREF (val, 0);
27855 eolvalue = AREF (val, 2);
27856
27857 if (multibyte)
27858 buf += CHAR_STRING (XFIXNAT (CODING_ATTR_MNEMONIC (attrs)),
27859 (unsigned char *) buf);
27860 else
27861 *buf++ = ' ';
27862
27863 if (eol_flag)
27864 {
27865
27866
27867 if (NILP (eolvalue))
27868 eoltype = eol_mnemonic_undecided;
27869 else if (VECTORP (eolvalue))
27870 eoltype = eol_mnemonic_undecided;
27871 else
27872 eoltype = (EQ (eolvalue, Qunix)
27873 ? eol_mnemonic_unix
27874 : EQ (eolvalue, Qdos)
27875 ? eol_mnemonic_dos : eol_mnemonic_mac);
27876 }
27877 }
27878
27879 if (eol_flag)
27880 {
27881
27882 if (STRINGP (eoltype))
27883 {
27884 eol_str = SDATA (eoltype);
27885 eol_str_len = SBYTES (eoltype);
27886 }
27887 else if (CHARACTERP (eoltype))
27888 {
27889 int c = XFIXNAT (eoltype);
27890 return buf + CHAR_STRING (c, (unsigned char *) buf);
27891 }
27892 else
27893 {
27894 eol_str = invalid_eol_type;
27895 eol_str_len = sizeof (invalid_eol_type) - 1;
27896 }
27897 memcpy (buf, eol_str, eol_str_len);
27898 buf += eol_str_len;
27899 }
27900
27901 return buf;
27902 }
27903
27904
27905
27906
27907 static int
27908 percent99 (ptrdiff_t n, ptrdiff_t d)
27909 {
27910 int percent = (d - 1 + 100.0 * n) / d;
27911 return min (percent, 99);
27912 }
27913
27914
27915
27916
27917
27918
27919
27920
27921
27922 static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
27923
27924 static const char *
27925 decode_mode_spec (struct window *w, register int c, int field_width,
27926 Lisp_Object *string)
27927 {
27928 Lisp_Object obj;
27929 struct frame *f = XFRAME (WINDOW_FRAME (w));
27930 char *decode_mode_spec_buf = f->decode_mode_spec_buffer;
27931
27932
27933
27934
27935
27936 int width = min (field_width, FRAME_MESSAGE_BUF_SIZE (f));
27937 struct buffer *b = current_buffer;
27938
27939 obj = Qnil;
27940 *string = Qnil;
27941
27942 switch (c)
27943 {
27944 case '*':
27945 if (!NILP (BVAR (b, read_only)))
27946 return "%";
27947 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
27948 return "*";
27949 return "-";
27950
27951 case '+':
27952
27953 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
27954 return "*";
27955 if (!NILP (BVAR (b, read_only)))
27956 return "%";
27957 return "-";
27958
27959 case '&':
27960
27961 if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
27962 return "*";
27963 return "-";
27964
27965 case '%':
27966 return "%";
27967
27968 case '[':
27969 {
27970 int i;
27971 char *p;
27972
27973 if (command_loop_level > 5)
27974 return "[[[... ";
27975 p = decode_mode_spec_buf;
27976 for (i = 0; i < command_loop_level; i++)
27977 *p++ = '[';
27978 *p = 0;
27979 return decode_mode_spec_buf;
27980 }
27981
27982 case ']':
27983 {
27984 int i;
27985 char *p;
27986
27987 if (command_loop_level > 5)
27988 return " ...]]]";
27989 p = decode_mode_spec_buf;
27990 for (i = 0; i < command_loop_level; i++)
27991 *p++ = ']';
27992 *p = 0;
27993 return decode_mode_spec_buf;
27994 }
27995
27996 case '-':
27997 {
27998 register int i;
27999
28000
28001 if (mode_line_target == MODE_LINE_NOPROP
28002 || mode_line_target == MODE_LINE_STRING)
28003 return "--";
28004 if (field_width <= 0
28005 || field_width > sizeof (lots_of_dashes))
28006 {
28007 for (i = 0; i < FRAME_MESSAGE_BUF_SIZE (f) - 1; ++i)
28008 decode_mode_spec_buf[i] = '-';
28009 decode_mode_spec_buf[i] = '\0';
28010 return decode_mode_spec_buf;
28011 }
28012 else
28013 return lots_of_dashes;
28014 }
28015
28016 case 'b':
28017 obj = BVAR (b, name);
28018 break;
28019
28020 case 'c':
28021 case 'C':
28022
28023
28024
28025
28026
28027 if (mode_line_target == MODE_LINE_TITLE)
28028 return "";
28029 else
28030 {
28031 ptrdiff_t col = current_column ();
28032 int disp_col = (c == 'C') ? col + 1 : col;
28033 w->column_number_displayed = col;
28034 pint2str (decode_mode_spec_buf, width, disp_col);
28035 return decode_mode_spec_buf;
28036 }
28037
28038 case 'e':
28039 #if !defined SYSTEM_MALLOC && !defined HYBRID_MALLOC
28040 {
28041 if (NILP (Vmemory_full))
28042 return "";
28043 else
28044 return "!MEM FULL! ";
28045 }
28046 #else
28047 return "";
28048 #endif
28049
28050 case 'F':
28051
28052 if (!NILP (f->title))
28053 return SSDATA (f->title);
28054 if (f->explicit_name || ! FRAME_WINDOW_P (f))
28055 return SSDATA (f->name);
28056 return "Emacs";
28057
28058 case 'f':
28059 obj = BVAR (b, filename);
28060 break;
28061
28062 case 'i':
28063 {
28064 ptrdiff_t size = ZV - BEGV;
28065 pint2str (decode_mode_spec_buf, width, size);
28066 return decode_mode_spec_buf;
28067 }
28068
28069 case 'I':
28070 {
28071 ptrdiff_t size = ZV - BEGV;
28072 pint2hrstr (decode_mode_spec_buf, width, size);
28073 return decode_mode_spec_buf;
28074 }
28075
28076 case 'l':
28077 {
28078 ptrdiff_t startpos, startpos_byte, line, linepos, linepos_byte;
28079 ptrdiff_t topline, nlines, height;
28080 ptrdiff_t junk;
28081
28082
28083 if (mode_line_target == MODE_LINE_TITLE)
28084 return "";
28085
28086 startpos = marker_position (w->start);
28087 startpos_byte = marker_byte_position (w->start);
28088 height = WINDOW_TOTAL_LINES (w);
28089
28090
28091
28092
28093
28094
28095
28096
28097 if (!(BUF_BEGV_BYTE (b) <= startpos_byte
28098 && startpos_byte <= BUF_ZV_BYTE (b)))
28099 {
28100 startpos = BUF_BEGV (b);
28101 startpos_byte = BUF_BEGV_BYTE (b);
28102 w->base_line_pos = 0;
28103 w->base_line_number = 0;
28104 }
28105
28106
28107
28108 if (w->base_line_pos == -1)
28109 goto no_value;
28110
28111
28112 if (FIXNUMP (Vline_number_display_limit)
28113 && BUF_ZV (b) - BUF_BEGV (b) > XFIXNUM (Vline_number_display_limit))
28114 {
28115 w->base_line_pos = 0;
28116 w->base_line_number = 0;
28117 goto no_value;
28118 }
28119
28120 if (w->base_line_number > 0
28121 && w->base_line_pos > 0
28122 && w->base_line_pos <= startpos)
28123 {
28124 line = w->base_line_number;
28125 linepos = w->base_line_pos;
28126 linepos_byte = buf_charpos_to_bytepos (b, linepos);
28127 }
28128 else
28129 {
28130 line = 1;
28131 linepos = BUF_BEGV (b);
28132 linepos_byte = BUF_BEGV_BYTE (b);
28133 }
28134
28135
28136 nlines = display_count_lines (linepos_byte,
28137 startpos_byte,
28138 startpos, &junk);
28139
28140 topline = nlines + line;
28141
28142
28143
28144
28145
28146 if (startpos == BUF_BEGV (b))
28147 {
28148 w->base_line_number = topline;
28149 w->base_line_pos = BUF_BEGV (b);
28150 }
28151 else if (nlines < height + 25 || nlines > height * 3 + 50
28152 || linepos == BUF_BEGV (b))
28153 {
28154 ptrdiff_t limit = BUF_BEGV (b);
28155 ptrdiff_t limit_byte = BUF_BEGV_BYTE (b);
28156 ptrdiff_t position;
28157 ptrdiff_t distance
28158 = (line_number_display_limit_width < 0 ? 0
28159 : INT_MULTIPLY_WRAPV (line_number_display_limit_width,
28160 height * 2 + 30,
28161 &distance)
28162 ? PTRDIFF_MAX : distance);
28163
28164 if (startpos - distance > limit)
28165 {
28166 limit = startpos - distance;
28167 limit_byte = CHAR_TO_BYTE (limit);
28168 }
28169
28170 nlines = display_count_lines (startpos_byte,
28171 limit_byte,
28172 - (height * 2 + 30),
28173 &position);
28174
28175
28176
28177 if (position == limit_byte && limit == startpos - distance)
28178 {
28179 w->base_line_pos = -1;
28180 w->base_line_number = 0;
28181 goto no_value;
28182 }
28183
28184 w->base_line_number = topline - nlines;
28185 w->base_line_pos = BYTE_TO_CHAR (position);
28186 }
28187
28188
28189 nlines = display_count_lines (startpos_byte,
28190 PT_BYTE, PT, &junk);
28191
28192
28193 line_number_displayed = true;
28194
28195
28196 pint2str (decode_mode_spec_buf, width, topline + nlines);
28197 return decode_mode_spec_buf;
28198 no_value:
28199 {
28200 char *p = decode_mode_spec_buf;
28201 int pad = width - 2;
28202 while (pad-- > 0)
28203 *p++ = ' ';
28204 *p++ = '?';
28205 *p++ = '?';
28206 *p = '\0';
28207 return decode_mode_spec_buf;
28208 }
28209 }
28210 break;
28211
28212 case 'm':
28213 obj = BVAR (b, mode_name);
28214 break;
28215
28216 case 'n':
28217 if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
28218 return " Narrow";
28219 break;
28220
28221
28222 case 'o':
28223 {
28224 ptrdiff_t toppos = marker_position (w->start);
28225 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28226 ptrdiff_t begv = BUF_BEGV (b);
28227 ptrdiff_t zv = BUF_ZV (b);
28228
28229 if (zv <= botpos)
28230 return toppos <= begv ? "All" : "Bottom";
28231 else if (toppos <= begv)
28232 return "Top";
28233 else
28234 {
28235 sprintf (decode_mode_spec_buf, "%2d%%",
28236 percent99 (toppos - begv, (toppos - begv) + (zv - botpos)));
28237 return decode_mode_spec_buf;
28238 }
28239 }
28240
28241
28242 case 'p':
28243 {
28244 ptrdiff_t pos = marker_position (w->start);
28245 ptrdiff_t begv = BUF_BEGV (b);
28246 ptrdiff_t zv = BUF_ZV (b);
28247
28248 if (w->window_end_pos <= BUF_Z (b) - zv)
28249 return pos <= begv ? "All" : "Bottom";
28250 else if (pos <= begv)
28251 return "Top";
28252 else
28253 {
28254 sprintf (decode_mode_spec_buf, "%2d%%",
28255 percent99 (pos - begv, zv - begv));
28256 return decode_mode_spec_buf;
28257 }
28258 }
28259
28260
28261 case 'P':
28262 {
28263 ptrdiff_t toppos = marker_position (w->start);
28264 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28265 ptrdiff_t begv = BUF_BEGV (b);
28266 ptrdiff_t zv = BUF_ZV (b);
28267
28268 if (zv <= botpos)
28269 return toppos <= begv ? "All" : "Bottom";
28270 else
28271 {
28272 sprintf (decode_mode_spec_buf,
28273 &"Top%2d%%"[begv < toppos ? sizeof "Top" - 1 : 0],
28274 percent99 (botpos - begv, zv - begv));
28275 return decode_mode_spec_buf;
28276 }
28277 }
28278
28279
28280
28281 case 'q':
28282 {
28283 ptrdiff_t toppos = marker_position (w->start);
28284 ptrdiff_t botpos = BUF_Z (b) - w->window_end_pos;
28285 ptrdiff_t begv = BUF_BEGV (b);
28286 ptrdiff_t zv = BUF_ZV (b);
28287 int top_perc, bot_perc;
28288
28289 if ((toppos <= begv) && (zv <= botpos))
28290 return "All ";
28291
28292 top_perc = toppos <= begv ? 0 : percent99 (toppos - begv, zv - begv);
28293 bot_perc = zv <= botpos ? 100 : percent99 (botpos - begv, zv - begv);
28294
28295 if (top_perc == bot_perc)
28296 sprintf (decode_mode_spec_buf, "%d%%", top_perc);
28297 else
28298 sprintf (decode_mode_spec_buf, "%d-%d%%", top_perc, bot_perc);
28299
28300 return decode_mode_spec_buf;
28301 }
28302
28303 case 's':
28304
28305 obj = Fget_buffer_process (Fcurrent_buffer ());
28306 if (NILP (obj))
28307 return "no process";
28308 #ifndef MSDOS
28309 obj = Fsymbol_name (Fprocess_status (obj));
28310 #endif
28311 break;
28312
28313 case '@':
28314 {
28315 specpdl_ref count = inhibit_garbage_collection ();
28316 Lisp_Object curdir = BVAR (current_buffer, directory);
28317 Lisp_Object val = Qnil;
28318
28319 if (STRINGP (curdir))
28320 val = safe_call1 (intern ("file-remote-p"), curdir);
28321
28322 val = unbind_to (count, val);
28323
28324 if (NILP (val))
28325 return "-";
28326 else
28327 return "@";
28328 }
28329
28330 case 'z':
28331
28332 case 'Z':
28333
28334 {
28335 bool eol_flag = (c == 'Z');
28336 char *p = decode_mode_spec_buf;
28337
28338 if (! FRAME_WINDOW_P (f))
28339 {
28340
28341
28342 p = decode_mode_spec_coding (CODING_ID_NAME
28343 (FRAME_KEYBOARD_CODING (f)->id),
28344 p, false);
28345 p = decode_mode_spec_coding (CODING_ID_NAME
28346 (FRAME_TERMINAL_CODING (f)->id),
28347 p, false);
28348 }
28349 p = decode_mode_spec_coding (BVAR (b, buffer_file_coding_system),
28350 p, eol_flag);
28351
28352 #if false
28353 #ifdef subprocesses
28354 obj = Fget_buffer_process (Fcurrent_buffer ());
28355 if (PROCESSP (obj))
28356 {
28357 p = decode_mode_spec_coding
28358 (XPROCESS (obj)->decode_coding_system, p, eol_flag);
28359 p = decode_mode_spec_coding
28360 (XPROCESS (obj)->encode_coding_system, p, eol_flag);
28361 }
28362 #endif
28363 #endif
28364 *p = 0;
28365 return decode_mode_spec_buf;
28366 }
28367 }
28368
28369 if (STRINGP (obj))
28370 {
28371 *string = obj;
28372 return SSDATA (obj);
28373 }
28374 else
28375 return "";
28376 }
28377
28378
28379
28380
28381 ptrdiff_t
28382 count_lines (ptrdiff_t start_byte, ptrdiff_t end_byte)
28383 {
28384 ptrdiff_t ignored;
28385 return display_count_lines (start_byte, end_byte, ZV, &ignored);
28386 }
28387
28388
28389
28390
28391
28392
28393
28394
28395
28396
28397
28398 static ptrdiff_t
28399 display_count_lines (ptrdiff_t start_byte,
28400 ptrdiff_t limit_byte, ptrdiff_t count,
28401 ptrdiff_t *byte_pos_ptr)
28402 {
28403 register unsigned char *cursor;
28404 unsigned char *base;
28405
28406 register ptrdiff_t ceiling;
28407 register unsigned char *ceiling_addr;
28408 ptrdiff_t orig_count = count;
28409
28410
28411
28412 bool selective_display
28413 = (!NILP (BVAR (current_buffer, selective_display))
28414 && !FIXNUMP (BVAR (current_buffer, selective_display)));
28415
28416 if (count > 0)
28417 {
28418 while (start_byte < limit_byte)
28419 {
28420 ceiling = BUFFER_CEILING_OF (start_byte);
28421 ceiling = min (limit_byte - 1, ceiling);
28422 ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
28423 base = (cursor = BYTE_POS_ADDR (start_byte));
28424
28425 do
28426 {
28427 if (selective_display)
28428 {
28429 while (*cursor != '\n' && *cursor != 015
28430 && ++cursor != ceiling_addr)
28431 continue;
28432 if (cursor == ceiling_addr)
28433 break;
28434 }
28435 else
28436 {
28437 cursor = memchr (cursor, '\n', ceiling_addr - cursor);
28438 if (! cursor)
28439 break;
28440 }
28441
28442 cursor++;
28443
28444 if (--count == 0)
28445 {
28446 start_byte += cursor - base;
28447 *byte_pos_ptr = start_byte;
28448 return orig_count;
28449 }
28450 }
28451 while (cursor < ceiling_addr);
28452
28453 start_byte += ceiling_addr - base;
28454 }
28455 }
28456 else
28457 {
28458 while (start_byte > limit_byte)
28459 {
28460 ceiling = BUFFER_FLOOR_OF (start_byte - 1);
28461 ceiling = max (limit_byte, ceiling);
28462 ceiling_addr = BYTE_POS_ADDR (ceiling);
28463 base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
28464 while (true)
28465 {
28466 if (selective_display)
28467 {
28468 while (--cursor >= ceiling_addr
28469 && *cursor != '\n' && *cursor != 015)
28470 continue;
28471 if (cursor < ceiling_addr)
28472 break;
28473 }
28474 else
28475 {
28476 cursor = memrchr (ceiling_addr, '\n', cursor - ceiling_addr);
28477 if (! cursor)
28478 break;
28479 }
28480
28481 if (++count == 0)
28482 {
28483 start_byte += cursor - base + 1;
28484 *byte_pos_ptr = start_byte;
28485
28486
28487 return - orig_count - 1;
28488 }
28489 }
28490 start_byte += ceiling_addr - base;
28491 }
28492 }
28493
28494 *byte_pos_ptr = limit_byte;
28495
28496 if (count < 0)
28497 return - orig_count + count;
28498 return orig_count - count;
28499
28500 }
28501
28502
28503
28504
28505
28506
28507
28508
28509
28510
28511
28512
28513
28514
28515
28516
28517
28518
28519
28520
28521
28522
28523
28524
28525
28526
28527
28528
28529
28530
28531
28532
28533
28534
28535
28536
28537
28538
28539
28540
28541
28542
28543
28544
28545
28546 static int
28547 display_string (const char *string, Lisp_Object lisp_string, Lisp_Object face_string,
28548 ptrdiff_t face_string_pos, ptrdiff_t start, struct it *it,
28549 int field_width, int precision, int max_x, int multibyte)
28550 {
28551 int hpos_at_start = it->hpos;
28552 int saved_face_id = it->face_id;
28553 struct glyph_row *row = it->glyph_row;
28554 ptrdiff_t it_charpos;
28555
28556
28557
28558 reseat_to_string (it, NILP (lisp_string) ? string : NULL, lisp_string,
28559 start, precision, field_width, multibyte);
28560
28561 if (string && STRINGP (lisp_string))
28562
28563
28564 it->stop_charpos = it->end_charpos;
28565
28566
28567
28568 if (STRINGP (face_string))
28569 {
28570 ptrdiff_t endptr;
28571 struct face *face;
28572
28573 it->face_id
28574 = face_at_string_position (it->w, face_string, face_string_pos,
28575 0, &endptr, it->base_face_id, false, 0);
28576 face = FACE_FROM_ID (it->f, it->face_id);
28577 it->face_box_p = face->box != FACE_NO_BOX;
28578
28579
28580
28581
28582 if (NILP (lisp_string))
28583 {
28584 Lisp_Object display = Fget_text_property (make_fixnum (0), Qdisplay,
28585 face_string);
28586 if (!NILP (display))
28587 {
28588 Lisp_Object min_width = plist_get (display, Qmin_width);
28589 if (!NILP (min_width))
28590 display_min_width (it, 0, face_string, min_width);
28591 }
28592 }
28593 }
28594
28595
28596
28597 if (max_x <= 0)
28598 max_x = it->last_visible_x;
28599 else
28600 max_x = min (max_x, it->last_visible_x);
28601
28602
28603
28604 if (it->current_x < it->first_visible_x)
28605 move_it_in_display_line_to (it, 100000, it->first_visible_x,
28606 MOVE_TO_POS | MOVE_TO_X);
28607
28608 row->ascent = it->max_ascent;
28609 row->height = it->max_ascent + it->max_descent;
28610 row->phys_ascent = it->max_phys_ascent;
28611 row->phys_height = it->max_phys_ascent + it->max_phys_descent;
28612 row->extra_line_spacing = it->max_extra_line_spacing;
28613
28614 if (STRINGP (it->string))
28615 it_charpos = IT_STRING_CHARPOS (*it);
28616 else
28617 it_charpos = IT_CHARPOS (*it);
28618
28619
28620
28621 while (it->current_x < max_x)
28622 {
28623 int x_before, x, n_glyphs_before, i, nglyphs;
28624
28625
28626 if (!get_next_display_element (it))
28627 break;
28628
28629
28630 x_before = it->current_x;
28631 n_glyphs_before = row->used[TEXT_AREA];
28632 PRODUCE_GLYPHS (it);
28633
28634 nglyphs = row->used[TEXT_AREA] - n_glyphs_before;
28635 i = 0;
28636 x = x_before;
28637 while (i < nglyphs)
28638 {
28639 struct glyph *glyph = row->glyphs[TEXT_AREA] + n_glyphs_before + i;
28640
28641 if (it->line_wrap != TRUNCATE
28642 && x + glyph->pixel_width > max_x)
28643 {
28644
28645 if (CHAR_GLYPH_PADDING_P (*glyph))
28646 {
28647
28648 if (row->reversed_p)
28649 unproduce_glyphs (it, row->used[TEXT_AREA]
28650 - n_glyphs_before);
28651 row->used[TEXT_AREA] = n_glyphs_before;
28652 it->current_x = x_before;
28653 }
28654 else
28655 {
28656 if (row->reversed_p)
28657 unproduce_glyphs (it, row->used[TEXT_AREA]
28658 - (n_glyphs_before + i));
28659 row->used[TEXT_AREA] = n_glyphs_before + i;
28660 it->current_x = x;
28661 }
28662 break;
28663 }
28664 else if (x + glyph->pixel_width >= it->first_visible_x)
28665 {
28666
28667 ++it->hpos;
28668 if (x < it->first_visible_x)
28669 row->x = x - it->first_visible_x;
28670 }
28671 else
28672 {
28673
28674
28675 emacs_abort ();
28676 }
28677
28678 row->ascent = max (row->ascent, it->max_ascent);
28679 row->height = max (row->height, it->max_ascent + it->max_descent);
28680 row->phys_ascent = max (row->phys_ascent, it->max_phys_ascent);
28681 row->phys_height = max (row->phys_height,
28682 it->max_phys_ascent + it->max_phys_descent);
28683 row->extra_line_spacing = max (row->extra_line_spacing,
28684 it->max_extra_line_spacing);
28685 x += glyph->pixel_width;
28686 ++i;
28687 }
28688
28689
28690 if (i < nglyphs)
28691 break;
28692
28693
28694 if (ITERATOR_AT_END_OF_LINE_P (it))
28695 {
28696 it->continuation_lines_width = 0;
28697 break;
28698 }
28699
28700 set_iterator_to_next (it, true);
28701 if (STRINGP (it->string))
28702 it_charpos = IT_STRING_CHARPOS (*it);
28703 else
28704 it_charpos = IT_CHARPOS (*it);
28705
28706
28707 if (it->line_wrap == TRUNCATE
28708 && it->current_x >= it->last_visible_x)
28709 {
28710
28711
28712 if (it_charpos < it->string_nchars)
28713 {
28714 if (!FRAME_WINDOW_P (it->f))
28715 {
28716 int ii, n;
28717
28718 if (it->current_x > it->last_visible_x)
28719 {
28720 if (!row->reversed_p)
28721 {
28722 for (ii = row->used[TEXT_AREA] - 1; ii > 0; --ii)
28723 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28724 break;
28725 }
28726 else
28727 {
28728 for (ii = 0; ii < row->used[TEXT_AREA]; ii++)
28729 if (!CHAR_GLYPH_PADDING_P (row->glyphs[TEXT_AREA][ii]))
28730 break;
28731 unproduce_glyphs (it, ii + 1);
28732 ii = row->used[TEXT_AREA] - (ii + 1);
28733 }
28734 for (n = row->used[TEXT_AREA]; ii < n; ++ii)
28735 {
28736 row->used[TEXT_AREA] = ii;
28737 produce_special_glyphs (it, IT_TRUNCATION);
28738 }
28739 }
28740 produce_special_glyphs (it, IT_TRUNCATION);
28741 }
28742 row->truncated_on_right_p = true;
28743 }
28744 break;
28745 }
28746 }
28747
28748
28749 if (it->first_visible_x
28750 && it_charpos > 0)
28751 {
28752 if (!FRAME_WINDOW_P (it->f)
28753 || (row->reversed_p
28754 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
28755 : WINDOW_LEFT_FRINGE_WIDTH (it->w)) == 0)
28756 insert_left_trunc_glyphs (it);
28757 row->truncated_on_left_p = true;
28758 }
28759
28760 it->face_id = saved_face_id;
28761
28762
28763 return it->hpos - hpos_at_start;
28764 }
28765
28766
28767
28768
28769
28770
28771
28772
28773
28774
28775
28776 int
28777 invisible_prop (Lisp_Object propval, Lisp_Object list)
28778 {
28779 Lisp_Object tail, proptail;
28780
28781 for (tail = list; CONSP (tail); tail = XCDR (tail))
28782 {
28783 register Lisp_Object tem;
28784 tem = XCAR (tail);
28785 if (EQ (propval, tem))
28786 return 1;
28787 if (CONSP (tem) && EQ (propval, XCAR (tem)))
28788 return NILP (XCDR (tem)) ? 1 : 2;
28789 }
28790
28791 if (CONSP (propval))
28792 {
28793 for (proptail = propval; CONSP (proptail); proptail = XCDR (proptail))
28794 {
28795 Lisp_Object propelt;
28796 propelt = XCAR (proptail);
28797 for (tail = list; CONSP (tail); tail = XCDR (tail))
28798 {
28799 register Lisp_Object tem;
28800 tem = XCAR (tail);
28801 if (EQ (propelt, tem))
28802 return 1;
28803 if (CONSP (tem) && EQ (propelt, XCAR (tem)))
28804 return NILP (XCDR (tem)) ? 1 : 2;
28805 }
28806 }
28807 }
28808
28809 return 0;
28810 }
28811
28812 DEFUN ("invisible-p", Finvisible_p, Sinvisible_p, 1, 1, 0,
28813 doc:
28814
28815
28816
28817
28818
28819
28820
28821
28822
28823
28824
28825 )
28826 (Lisp_Object pos)
28827 {
28828 Lisp_Object prop
28829 = (FIXNATP (pos) || MARKERP (pos)
28830 ? Fget_char_property (pos, Qinvisible, Qnil)
28831 : pos);
28832 int invis = TEXT_PROP_MEANS_INVISIBLE (prop);
28833 return (invis == 0 ? Qnil
28834 : invis == 1 ? Qt
28835 : make_fixnum (invis));
28836 }
28837
28838
28839
28840
28841
28842
28843
28844
28845
28846
28847
28848
28849
28850
28851
28852
28853
28854
28855
28856
28857
28858
28859
28860
28861
28862
28863
28864
28865
28866
28867
28868
28869
28870
28871
28872
28873
28874
28875
28876
28877
28878
28879
28880
28881
28882
28883
28884
28885
28886
28887
28888
28889
28890
28891
28892
28893
28894
28895
28896
28897
28898
28899
28900
28901
28902
28903
28904
28905
28906
28907
28908
28909
28910
28911
28912
28913
28914
28915
28916
28917
28918 static bool
28919 calc_pixel_width_or_height (double *res, struct it *it, Lisp_Object prop,
28920 struct font *font, bool width_p, int *align_to)
28921 {
28922
28923
28924
28925
28926 int lnum_pixel_width = it->line_number_produced_p ? it->lnum_pixel_width : 0;
28927 double pixels;
28928
28929 # define OK_PIXELS(val) (*res = (val), true)
28930 # define OK_ALIGN_TO(val) (*align_to = (val), true)
28931
28932 if (NILP (prop))
28933 return OK_PIXELS (0);
28934
28935 eassert (FRAME_LIVE_P (it->f));
28936
28937 if (SYMBOLP (prop))
28938 {
28939 if (SCHARS (SYMBOL_NAME (prop)) == 2)
28940 {
28941 char *unit = SSDATA (SYMBOL_NAME (prop));
28942
28943
28944 if (unit[0] == 'i' && unit[1] == 'n')
28945 pixels = 1.0;
28946 else if (unit[0] == 'm' && unit[1] == 'm')
28947 pixels = 25.4;
28948 else if (unit[0] == 'c' && unit[1] == 'm')
28949 pixels = 2.54;
28950 else
28951 pixels = 0;
28952 if (pixels > 0)
28953 {
28954 double ppi = (width_p ? FRAME_RES_X (it->f)
28955 : FRAME_RES_Y (it->f));
28956
28957 if (ppi > 0)
28958 return OK_PIXELS (ppi / pixels);
28959 return false;
28960 }
28961 }
28962
28963 #ifdef HAVE_WINDOW_SYSTEM
28964
28965 if (EQ (prop, Qheight))
28966 return OK_PIXELS (font
28967 ? normal_char_height (font, -1)
28968 : FRAME_LINE_HEIGHT (it->f));
28969
28970 if (EQ (prop, Qwidth))
28971 return OK_PIXELS (font
28972 ? FONT_WIDTH (font)
28973 : FRAME_COLUMN_WIDTH (it->f));
28974 #else
28975 if (EQ (prop, Qheight) || EQ (prop, Qwidth))
28976 return OK_PIXELS (1);
28977 #endif
28978
28979
28980 if (EQ (prop, Qtext))
28981 return OK_PIXELS (width_p
28982 ? (window_box_width (it->w, TEXT_AREA)
28983 - lnum_pixel_width)
28984 : WINDOW_BOX_HEIGHT_NO_MODE_LINE (it->w));
28985
28986
28987
28988
28989 if (align_to && *align_to < 0)
28990 {
28991 *res = 0;
28992
28993 if (EQ (prop, Qleft))
28994 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
28995 + lnum_pixel_width);
28996
28997 if (EQ (prop, Qright))
28998 return OK_ALIGN_TO (window_box_right_offset (it->w, TEXT_AREA));
28999
29000 if (EQ (prop, Qcenter))
29001 return OK_ALIGN_TO (window_box_left_offset (it->w, TEXT_AREA)
29002 + lnum_pixel_width
29003 + window_box_width (it->w, TEXT_AREA) / 2);
29004
29005 if (EQ (prop, Qleft_fringe))
29006 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29007 ? WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (it->w)
29008 : window_box_right_offset (it->w, LEFT_MARGIN_AREA));
29009
29010 if (EQ (prop, Qright_fringe))
29011 return OK_ALIGN_TO (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29012 ? window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29013 : window_box_right_offset (it->w, TEXT_AREA));
29014
29015 if (EQ (prop, Qleft_margin))
29016 return OK_ALIGN_TO (window_box_left_offset (it->w, LEFT_MARGIN_AREA));
29017
29018 if (EQ (prop, Qright_margin))
29019 return OK_ALIGN_TO (window_box_left_offset (it->w, RIGHT_MARGIN_AREA));
29020
29021 if (EQ (prop, Qscroll_bar))
29022 return OK_ALIGN_TO (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (it->w)
29023 ? 0
29024 : (window_box_right_offset (it->w, RIGHT_MARGIN_AREA)
29025 + (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (it->w)
29026 ? WINDOW_RIGHT_FRINGE_WIDTH (it->w)
29027 : 0)));
29028 }
29029 else
29030 {
29031
29032 if (EQ (prop, Qleft_fringe))
29033 return OK_PIXELS (WINDOW_LEFT_FRINGE_WIDTH (it->w));
29034 if (EQ (prop, Qright_fringe))
29035 return OK_PIXELS (WINDOW_RIGHT_FRINGE_WIDTH (it->w));
29036 if (EQ (prop, Qleft_margin))
29037 return OK_PIXELS (WINDOW_LEFT_MARGIN_WIDTH (it->w));
29038 if (EQ (prop, Qright_margin))
29039 return OK_PIXELS (WINDOW_RIGHT_MARGIN_WIDTH (it->w));
29040 if (EQ (prop, Qscroll_bar))
29041 return OK_PIXELS (WINDOW_SCROLL_BAR_AREA_WIDTH (it->w));
29042 }
29043
29044 prop = buffer_local_value (prop, it->w->contents);
29045 if (BASE_EQ (prop, Qunbound))
29046 prop = Qnil;
29047 }
29048
29049 if (NUMBERP (prop))
29050 {
29051 int base_unit = (width_p
29052 ? FRAME_COLUMN_WIDTH (it->f)
29053 : FRAME_LINE_HEIGHT (it->f));
29054 if (width_p && align_to && *align_to < 0)
29055 return OK_PIXELS (XFLOATINT (prop) * base_unit + lnum_pixel_width);
29056 return OK_PIXELS (XFLOATINT (prop) * base_unit);
29057 }
29058
29059 if (CONSP (prop))
29060 {
29061 Lisp_Object car = XCAR (prop);
29062 Lisp_Object cdr = XCDR (prop);
29063
29064 if (SYMBOLP (car))
29065 {
29066 #ifdef HAVE_WINDOW_SYSTEM
29067
29068 if (FRAME_WINDOW_P (it->f)
29069 && valid_image_p (prop))
29070 {
29071 ptrdiff_t id = lookup_image (it->f, prop, it->face_id);
29072 struct image *img = IMAGE_FROM_ID (it->f, id);
29073
29074 return OK_PIXELS (width_p ? img->width : img->height);
29075 }
29076
29077 if (FRAME_WINDOW_P (it->f) && valid_xwidget_spec_p (prop))
29078 {
29079
29080 return OK_PIXELS (100);
29081 }
29082 #endif
29083
29084
29085 if (EQ (car, Qplus) || EQ (car, Qminus))
29086 {
29087 bool first = true;
29088 double px;
29089
29090 pixels = 0;
29091 while (CONSP (cdr))
29092 {
29093 if (!calc_pixel_width_or_height (&px, it, XCAR (cdr),
29094 font, width_p, align_to))
29095 return false;
29096 if (first)
29097 pixels = (EQ (car, Qplus) ? px : -px), first = false;
29098 else
29099 pixels += px;
29100 cdr = XCDR (cdr);
29101 }
29102 if (EQ (car, Qminus))
29103 pixels = -pixels;
29104 return OK_PIXELS (pixels);
29105 }
29106
29107 car = buffer_local_value (car, it->w->contents);
29108 if (BASE_EQ (car, Qunbound))
29109 car = Qnil;
29110 }
29111
29112
29113 if (NUMBERP (car))
29114 {
29115 double fact;
29116 int offset =
29117 width_p && align_to && *align_to < 0 ? lnum_pixel_width : 0;
29118 pixels = XFLOATINT (car);
29119 if (NILP (cdr))
29120 return OK_PIXELS (pixels + offset);
29121 if (calc_pixel_width_or_height (&fact, it, cdr,
29122 font, width_p, align_to))
29123 return OK_PIXELS (pixels * fact + offset);
29124 return false;
29125 }
29126
29127 return false;
29128 }
29129
29130 return false;
29131 }
29132
29133 void
29134 get_font_ascent_descent (struct font *font, int *ascent, int *descent)
29135 {
29136 #ifdef HAVE_WINDOW_SYSTEM
29137 normal_char_ascent_descent (font, -1, ascent, descent);
29138 #else
29139 *ascent = 1;
29140 *descent = 0;
29141 #endif
29142 }
29143
29144
29145
29146
29147
29148
29149 #ifdef HAVE_WINDOW_SYSTEM
29150
29151 #ifdef GLYPH_DEBUG
29152
29153 extern void dump_glyph_string (struct glyph_string *) EXTERNALLY_VISIBLE;
29154 void
29155 dump_glyph_string (struct glyph_string *s)
29156 {
29157 fputs ("glyph string\n", stderr);
29158 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
29159 s->x, s->y, s->width, s->height);
29160 fprintf (stderr, " ybase = %d\n", s->ybase);
29161 fprintf (stderr, " hl = %u\n", s->hl);
29162 fprintf (stderr, " left overhang = %d, right = %d\n",
29163 s->left_overhang, s->right_overhang);
29164 fprintf (stderr, " nchars = %d\n", s->nchars);
29165 fprintf (stderr, " extends to end of line = %d\n",
29166 s->extends_to_end_of_line_p);
29167 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
29168 fprintf (stderr, " bg width = %d\n", s->background_width);
29169 }
29170
29171 #endif
29172
29173
29174
29175
29176
29177
29178
29179
29180
29181 #ifdef HAVE_NTGUI
29182
29183
29184
29185
29186
29187 # define ALLOCATE_HDC(hdc, f) \
29188 Lisp_Object prev_quit = Vinhibit_quit; \
29189 Vinhibit_quit = Qt; \
29190 HDC hdc = get_frame_dc ((f))
29191 # define RELEASE_HDC(hdc, f) \
29192 release_frame_dc ((f), (hdc)); \
29193 Vinhibit_quit = prev_quit
29194 #else
29195 # define ALLOCATE_HDC(hdc, f)
29196 # define RELEASE_HDC(hdc, f)
29197 #endif
29198
29199 static void
29200 init_glyph_string (struct glyph_string *s,
29201 #ifdef HAVE_NTGUI
29202 HDC hdc,
29203 #endif
29204 unsigned *char2b, struct window *w, struct glyph_row *row,
29205 enum glyph_row_area area, int start, enum draw_glyphs_face hl)
29206 {
29207 memset (s, 0, sizeof *s);
29208 s->w = w;
29209 s->f = XFRAME (w->frame);
29210 #ifdef HAVE_NTGUI
29211 s->hdc = hdc;
29212 #endif
29213 s->char2b = char2b;
29214 s->hl = hl;
29215 s->row = row;
29216 s->area = area;
29217 s->first_glyph = row->glyphs[area] + start;
29218 s->height = row->height;
29219 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
29220 s->ybase = s->y + row->ascent;
29221 }
29222
29223
29224
29225
29226
29227 static void
29228 append_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29229 struct glyph_string *h, struct glyph_string *t)
29230 {
29231 if (h)
29232 {
29233 if (*head)
29234 (*tail)->next = h;
29235 else
29236 *head = h;
29237 h->prev = *tail;
29238 *tail = t;
29239 }
29240 }
29241
29242
29243
29244
29245
29246
29247 static void
29248 prepend_glyph_string_lists (struct glyph_string **head, struct glyph_string **tail,
29249 struct glyph_string *h, struct glyph_string *t)
29250 {
29251 if (h)
29252 {
29253 if (*head)
29254 (*head)->prev = t;
29255 else
29256 *tail = t;
29257 t->next = *head;
29258 *head = h;
29259 }
29260 }
29261
29262
29263
29264
29265
29266 static void
29267 append_glyph_string (struct glyph_string **head, struct glyph_string **tail,
29268 struct glyph_string *s)
29269 {
29270 s->next = s->prev = NULL;
29271 append_glyph_string_lists (head, tail, s, s);
29272 }
29273
29274
29275
29276
29277
29278
29279
29280
29281 static struct face *
29282 get_char_face_and_encoding (struct frame *f, int c, int face_id,
29283 unsigned *char2b, bool display_p)
29284 {
29285 struct face *face = FACE_FROM_ID (f, face_id);
29286 unsigned code = 0;
29287
29288 if (face->font)
29289 {
29290 code = face->font->driver->encode_char (face->font, c);
29291
29292 if (code == FONT_INVALID_CODE)
29293 code = 0;
29294 }
29295
29296 *char2b = code & 0xFFFF;
29297
29298
29299 #ifdef HAVE_X_WINDOWS
29300 if (display_p)
29301 #endif
29302 {
29303 eassert (face != NULL);
29304 prepare_face_for_display (f, face);
29305 }
29306
29307 return face;
29308 }
29309
29310
29311
29312
29313
29314
29315 static struct face *
29316 get_glyph_face_and_encoding (struct frame *f, struct glyph *glyph,
29317 unsigned *char2b)
29318 {
29319 struct face *face;
29320 unsigned code = 0;
29321
29322 eassert (glyph->type == CHAR_GLYPH);
29323 face = FACE_FROM_ID (f, glyph->face_id);
29324
29325
29326 prepare_face_for_display (f, face);
29327
29328 if (face->font)
29329 {
29330 if (CHAR_BYTE8_P (glyph->u.ch))
29331 code = CHAR_TO_BYTE8 (glyph->u.ch);
29332 else
29333 code = face->font->driver->encode_char (face->font, glyph->u.ch);
29334
29335 if (code == FONT_INVALID_CODE)
29336 code = 0;
29337 }
29338
29339
29340 *char2b = code & 0xFFFF;
29341 return face;
29342 }
29343
29344
29345
29346
29347
29348 static bool
29349 get_char_glyph_code (int c, struct font *font, unsigned *char2b)
29350 {
29351 unsigned code;
29352
29353 if (CHAR_BYTE8_P (c))
29354 code = CHAR_TO_BYTE8 (c);
29355 else
29356 code = font->driver->encode_char (font, c);
29357
29358 if (code == FONT_INVALID_CODE)
29359 return false;
29360
29361
29362 *char2b = code & 0xFFFF;
29363 return true;
29364 }
29365
29366
29367
29368
29369
29370
29371
29372
29373
29374
29375
29376
29377 static int
29378 fill_composite_glyph_string (struct glyph_string *s, struct face *base_face,
29379 int overlaps)
29380 {
29381 int i;
29382
29383
29384
29385 struct face *face;
29386
29387 eassert (s);
29388
29389 s->for_overlaps = overlaps;
29390 s->face = NULL;
29391 s->font = NULL;
29392 for (i = s->cmp_from; i < s->cmp->glyph_len; i++)
29393 {
29394 int c = COMPOSITION_GLYPH (s->cmp, i);
29395
29396
29397
29398 if (c != '\t')
29399 {
29400 int face_id = FACE_FOR_CHAR (s->f, base_face->ascii_face, c,
29401 -1, Qnil);
29402
29403 face = get_char_face_and_encoding (s->f, c, face_id,
29404 s->char2b + i, true);
29405 if (face)
29406 {
29407 if (! s->face)
29408 {
29409 s->face = face;
29410 s->font = s->face->font;
29411 }
29412 else if (s->face != face)
29413 break;
29414 }
29415 }
29416 ++s->nchars;
29417 }
29418 s->cmp_to = i;
29419
29420 if (s->face == NULL)
29421 {
29422 s->face = base_face->ascii_face;
29423 s->font = s->face->font;
29424 }
29425
29426 if (s->hl == DRAW_MOUSE_FACE
29427 || (s->hl == DRAW_CURSOR
29428 && MATRIX_ROW (s->w->current_matrix,
29429 s->w->phys_cursor.vpos)->mouse_face_p
29430 && cursor_in_mouse_face_p (s->w)))
29431 {
29432 int c = COMPOSITION_GLYPH (s->cmp, 0);
29433 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29434 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29435 if (!s->face)
29436 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29437
29438 s->face = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face, c, -1, Qnil));
29439 prepare_face_for_display (s->f, s->face);
29440 }
29441
29442
29443
29444 s->width = s->first_glyph->pixel_width;
29445
29446
29447
29448
29449
29450 if (s->font == NULL)
29451 {
29452 s->font_not_found_p = true;
29453 s->font = FRAME_FONT (s->f);
29454 }
29455
29456
29457 s->ybase += s->first_glyph->voffset;
29458
29459 return s->cmp_to;
29460 }
29461
29462 static int
29463 fill_gstring_glyph_string (struct glyph_string *s, int face_id,
29464 int start, int end, int overlaps)
29465 {
29466 struct glyph *glyph, *last;
29467 int voffset;
29468 Lisp_Object lgstring;
29469 int i;
29470 bool glyph_not_available_p;
29471
29472 s->for_overlaps = overlaps;
29473 glyph = s->row->glyphs[s->area] + start;
29474 last = s->row->glyphs[s->area] + end;
29475 voffset = glyph->voffset;
29476 glyph_not_available_p = glyph->glyph_not_available_p;
29477 s->cmp_id = glyph->u.cmp.id;
29478 s->cmp_from = glyph->slice.cmp.from;
29479 s->cmp_to = glyph->slice.cmp.to + 1;
29480 if (s->hl == DRAW_MOUSE_FACE
29481 || (s->hl == DRAW_CURSOR
29482 && MATRIX_ROW (s->w->current_matrix,
29483 s->w->phys_cursor.vpos)->mouse_face_p
29484 && cursor_in_mouse_face_p (s->w)))
29485 {
29486 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29487 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29488 if (!s->face)
29489 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29490 prepare_face_for_display (s->f, s->face);
29491 }
29492 else
29493 s->face = FACE_FROM_ID (s->f, face_id);
29494 lgstring = composition_gstring_from_id (s->cmp_id);
29495 s->font = XFONT_OBJECT (LGSTRING_FONT (lgstring));
29496
29497
29498 s->width = s->first_glyph->pixel_width;
29499 glyph++;
29500 while (glyph < last
29501 && glyph->u.cmp.automatic
29502 && glyph->u.cmp.id == s->cmp_id
29503 && glyph->face_id == face_id
29504 && s->cmp_to == glyph->slice.cmp.from
29505 && glyph->glyph_not_available_p == glyph_not_available_p)
29506 {
29507 s->width += glyph->pixel_width;
29508 s->cmp_to = (glyph++)->slice.cmp.to + 1;
29509 }
29510
29511 for (i = s->cmp_from; i < s->cmp_to; i++)
29512 {
29513 Lisp_Object lglyph = LGSTRING_GLYPH (lgstring, i);
29514 unsigned code = LGLYPH_CODE (lglyph);
29515
29516
29517 s->char2b[i] = code & 0xFFFF;
29518 }
29519
29520
29521
29522
29523 if (glyph_not_available_p)
29524 s->font_not_found_p = true;
29525
29526
29527 s->ybase += voffset;
29528
29529 return glyph - s->row->glyphs[s->area];
29530 }
29531
29532
29533
29534
29535
29536
29537
29538 static int
29539 fill_glyphless_glyph_string (struct glyph_string *s, int face_id,
29540 int start, int end, int overlaps)
29541 {
29542 struct glyph *glyph, *last;
29543 int voffset;
29544
29545 eassert (s->first_glyph->type == GLYPHLESS_GLYPH);
29546 s->for_overlaps = overlaps;
29547 glyph = s->row->glyphs[s->area] + start;
29548 last = s->row->glyphs[s->area] + end;
29549 voffset = glyph->voffset;
29550 s->face = FACE_FROM_ID (s->f, face_id);
29551 s->font = s->face->font ? s->face->font : FRAME_FONT (s->f);
29552 if (s->hl == DRAW_MOUSE_FACE
29553 || (s->hl == DRAW_CURSOR
29554 && MATRIX_ROW (s->w->current_matrix,
29555 s->w->phys_cursor.vpos)->mouse_face_p
29556 && cursor_in_mouse_face_p (s->w)))
29557 {
29558 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29559 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29560 if (!s->face)
29561 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29562 prepare_face_for_display (s->f, s->face);
29563 }
29564 s->nchars = 1;
29565 s->width = glyph->pixel_width;
29566 glyph++;
29567 while (glyph < last
29568 && glyph->type == GLYPHLESS_GLYPH
29569 && glyph->voffset == voffset
29570 && glyph->face_id == face_id)
29571 {
29572 s->nchars++;
29573 s->width += glyph->pixel_width;
29574 glyph++;
29575 }
29576 s->ybase += voffset;
29577 return glyph - s->row->glyphs[s->area];
29578 }
29579
29580
29581
29582
29583
29584
29585
29586
29587
29588
29589
29590 static int
29591 fill_glyph_string (struct glyph_string *s, int face_id,
29592 int start, int end, int overlaps)
29593 {
29594 struct glyph *glyph, *last;
29595 int voffset;
29596 bool glyph_not_available_p;
29597
29598 eassert (s->f == XFRAME (s->w->frame));
29599 eassert (s->nchars == 0);
29600 eassert (start >= 0 && end > start);
29601
29602 s->for_overlaps = overlaps;
29603 glyph = s->row->glyphs[s->area] + start;
29604 last = s->row->glyphs[s->area] + end;
29605 voffset = glyph->voffset;
29606 s->padding_p = glyph->padding_p;
29607 glyph_not_available_p = glyph->glyph_not_available_p;
29608
29609 while (glyph < last
29610 && glyph->type == CHAR_GLYPH
29611 && glyph->voffset == voffset
29612
29613 && glyph->face_id == face_id
29614 && glyph->glyph_not_available_p == glyph_not_available_p)
29615 {
29616 s->face = get_glyph_face_and_encoding (s->f, glyph,
29617 s->char2b + s->nchars);
29618 ++s->nchars;
29619 eassert (s->nchars <= end - start);
29620 s->width += glyph->pixel_width;
29621 if (glyph++->padding_p != s->padding_p)
29622 break;
29623 }
29624
29625 s->font = s->face->font;
29626
29627 if (s->hl == DRAW_MOUSE_FACE
29628 || (s->hl == DRAW_CURSOR
29629 && MATRIX_ROW (s->w->current_matrix,
29630 s->w->phys_cursor.vpos)->mouse_face_p
29631 && cursor_in_mouse_face_p (s->w)))
29632 {
29633 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29634 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29635 if (!s->face)
29636 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29637 s->face
29638 = FACE_FROM_ID (s->f, FACE_FOR_CHAR (s->f, s->face,
29639 s->first_glyph->u.ch, -1, Qnil));
29640 prepare_face_for_display (s->f, s->face);
29641 }
29642
29643
29644
29645
29646
29647 if (s->font == NULL || glyph_not_available_p)
29648 {
29649 s->font_not_found_p = true;
29650 s->font = FRAME_FONT (s->f);
29651 }
29652
29653
29654 s->ybase += voffset;
29655
29656 eassert (s->face && s->face->gc);
29657 return glyph - s->row->glyphs[s->area];
29658 }
29659
29660
29661
29662
29663 static void
29664 fill_image_glyph_string (struct glyph_string *s)
29665 {
29666 eassert (s->first_glyph->type == IMAGE_GLYPH);
29667 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
29668 eassert (s->img);
29669 s->slice = s->first_glyph->slice.img;
29670 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29671 s->font = s->face->font;
29672 if (s->hl == DRAW_MOUSE_FACE
29673 || (s->hl == DRAW_CURSOR
29674 && MATRIX_ROW (s->w->current_matrix,
29675 s->w->phys_cursor.vpos)->mouse_face_p
29676 && cursor_in_mouse_face_p (s->w)))
29677 {
29678 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29679 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29680 if (!s->face)
29681 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29682 prepare_face_for_display (s->f, s->face);
29683 }
29684 s->width = s->first_glyph->pixel_width;
29685
29686
29687 s->ybase += s->first_glyph->voffset;
29688 }
29689
29690
29691 #ifdef HAVE_XWIDGETS
29692 static void
29693 fill_xwidget_glyph_string (struct glyph_string *s)
29694 {
29695 eassert (s->first_glyph->type == XWIDGET_GLYPH);
29696 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
29697 s->font = s->face->font;
29698 if (s->hl == DRAW_MOUSE_FACE
29699 || (s->hl == DRAW_CURSOR
29700 && MATRIX_ROW (s->w->current_matrix,
29701 s->w->phys_cursor.vpos)->mouse_face_p
29702 && cursor_in_mouse_face_p (s->w)))
29703 {
29704 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29705 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29706 if (!s->face)
29707 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29708 prepare_face_for_display (s->f, s->face);
29709 }
29710 s->width = s->first_glyph->pixel_width;
29711 s->ybase += s->first_glyph->voffset;
29712 s->xwidget = xwidget_from_id (s->first_glyph->u.xwidget);
29713 }
29714 #endif
29715
29716
29717
29718
29719
29720
29721
29722 static int
29723 fill_stretch_glyph_string (struct glyph_string *s, int start, int end)
29724 {
29725 struct glyph *glyph, *last;
29726 int voffset, face_id;
29727
29728 eassert (s->first_glyph->type == STRETCH_GLYPH);
29729
29730 glyph = s->row->glyphs[s->area] + start;
29731 last = s->row->glyphs[s->area] + end;
29732 face_id = glyph->face_id;
29733 s->face = FACE_FROM_ID (s->f, face_id);
29734 s->font = s->face->font;
29735 if (s->hl == DRAW_MOUSE_FACE
29736 || (s->hl == DRAW_CURSOR
29737 && MATRIX_ROW (s->w->current_matrix,
29738 s->w->phys_cursor.vpos)->mouse_face_p
29739 && cursor_in_mouse_face_p (s->w)))
29740 {
29741 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (s->f);
29742 s->face = FACE_FROM_ID_OR_NULL (s->f, hlinfo->mouse_face_face_id);
29743 if (!s->face)
29744 s->face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
29745 prepare_face_for_display (s->f, s->face);
29746 }
29747 s->width = glyph->pixel_width;
29748 s->nchars = 1;
29749 voffset = glyph->voffset;
29750
29751 for (++glyph;
29752 (glyph < last
29753 && glyph->type == STRETCH_GLYPH
29754 && glyph->voffset == voffset
29755 && glyph->face_id == face_id);
29756 ++glyph)
29757 s->width += glyph->pixel_width;
29758
29759
29760 s->ybase += voffset;
29761
29762
29763
29764 eassert (s->face);
29765 return glyph - s->row->glyphs[s->area];
29766 }
29767
29768 static struct font_metrics *
29769 get_per_char_metric (struct font *font, const unsigned *char2b)
29770 {
29771 static struct font_metrics metrics;
29772
29773 if (! font)
29774 return NULL;
29775 if (*char2b == FONT_INVALID_CODE)
29776 return NULL;
29777
29778 font->driver->text_extents (font, char2b, 1, &metrics);
29779 return &metrics;
29780 }
29781
29782
29783
29784
29785
29786
29787
29788 static void
29789 normal_char_ascent_descent (struct font *font, int c, int *ascent, int *descent)
29790 {
29791 *ascent = FONT_BASE (font);
29792 *descent = FONT_DESCENT (font);
29793
29794 if (FONT_TOO_HIGH (font))
29795 {
29796 unsigned char2b;
29797
29798
29799
29800 if (get_char_glyph_code (c >= 0 ? c : '{', font, &char2b))
29801 {
29802 struct font_metrics *pcm = get_per_char_metric (font, &char2b);
29803 eassume (pcm);
29804
29805 if (!(pcm->width == 0 && pcm->rbearing == 0 && pcm->lbearing == 0))
29806 {
29807
29808
29809
29810 *ascent = pcm->ascent + 1;
29811 *descent = pcm->descent + 1;
29812 }
29813 }
29814 }
29815 }
29816
29817
29818
29819
29820
29821
29822 static int
29823 normal_char_height (struct font *font, int c)
29824 {
29825 int ascent, descent;
29826
29827 normal_char_ascent_descent (font, c, &ascent, &descent);
29828
29829 return ascent + descent;
29830 }
29831
29832
29833
29834
29835
29836
29837 void
29838 gui_get_glyph_overhangs (struct glyph *glyph, struct frame *f, int *left, int *right)
29839 {
29840 *left = *right = 0;
29841
29842 if (glyph->type == CHAR_GLYPH)
29843 {
29844 unsigned char2b;
29845 struct face *face = get_glyph_face_and_encoding (f, glyph, &char2b);
29846 if (face->font)
29847 {
29848 struct font_metrics *pcm = get_per_char_metric (face->font, &char2b);
29849 if (pcm)
29850 {
29851 if (pcm->rbearing > pcm->width)
29852 *right = pcm->rbearing - pcm->width;
29853 if (pcm->lbearing < 0)
29854 *left = -pcm->lbearing;
29855 }
29856 }
29857 }
29858 else if (glyph->type == COMPOSITE_GLYPH)
29859 {
29860 if (! glyph->u.cmp.automatic)
29861 {
29862 struct composition *cmp = composition_table[glyph->u.cmp.id];
29863
29864 if (cmp->rbearing > cmp->pixel_width)
29865 *right = cmp->rbearing - cmp->pixel_width;
29866 if (cmp->lbearing < 0)
29867 *left = - cmp->lbearing;
29868 }
29869 else
29870 {
29871 Lisp_Object gstring = composition_gstring_from_id (glyph->u.cmp.id);
29872 struct font_metrics metrics;
29873
29874 composition_gstring_width (gstring, glyph->slice.cmp.from,
29875 glyph->slice.cmp.to + 1, &metrics);
29876 if (metrics.rbearing > metrics.width)
29877 *right = metrics.rbearing - metrics.width;
29878 if (metrics.lbearing < 0)
29879 *left = - metrics.lbearing;
29880 }
29881 }
29882 }
29883
29884
29885
29886
29887
29888
29889 static int
29890 left_overwritten (struct glyph_string *s)
29891 {
29892 int k;
29893
29894 if (s->left_overhang)
29895 {
29896 int x = 0, i;
29897 struct glyph *glyphs = s->row->glyphs[s->area];
29898 int first = s->first_glyph - glyphs;
29899
29900 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
29901 x -= glyphs[i].pixel_width;
29902
29903 k = i + 1;
29904 }
29905 else
29906 k = -1;
29907
29908 return k;
29909 }
29910
29911
29912
29913
29914
29915
29916 static int
29917 left_overwriting (struct glyph_string *s)
29918 {
29919 int i, k, x;
29920 struct glyph *glyphs = s->row->glyphs[s->area];
29921 int first = s->first_glyph - glyphs;
29922
29923 k = -1;
29924 x = 0;
29925 for (i = first - 1; i >= 0; --i)
29926 {
29927 int left, right;
29928 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
29929 if (x + right > 0)
29930 k = i;
29931 x -= glyphs[i].pixel_width;
29932 }
29933
29934 return k;
29935 }
29936
29937
29938
29939
29940
29941
29942 static int
29943 right_overwritten (struct glyph_string *s)
29944 {
29945 int k = -1;
29946
29947 if (s->right_overhang)
29948 {
29949 int x = 0, i;
29950 struct glyph *glyphs = s->row->glyphs[s->area];
29951 int first = (s->first_glyph - glyphs
29952 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
29953 int end = s->row->used[s->area];
29954
29955 for (i = first; i < end && s->right_overhang > x; ++i)
29956 x += glyphs[i].pixel_width;
29957
29958 k = i;
29959 }
29960
29961 return k;
29962 }
29963
29964
29965
29966
29967
29968
29969 static int
29970 right_overwriting (struct glyph_string *s)
29971 {
29972 int i, k, x;
29973 int end = s->row->used[s->area];
29974 struct glyph *glyphs = s->row->glyphs[s->area];
29975 int first = (s->first_glyph - glyphs
29976 + (s->first_glyph->type == COMPOSITE_GLYPH ? 1 : s->nchars));
29977
29978 k = -1;
29979 x = 0;
29980 for (i = first; i < end; ++i)
29981 {
29982 int left, right;
29983 gui_get_glyph_overhangs (glyphs + i, s->f, &left, &right);
29984 if (x - left < 0)
29985 k = i;
29986 x += glyphs[i].pixel_width;
29987 }
29988
29989 return k;
29990 }
29991
29992
29993
29994
29995
29996
29997
29998
29999
30000
30001
30002 static void
30003 set_glyph_string_background_width (struct glyph_string *s, int start, int last_x)
30004 {
30005
30006
30007
30008 if (start == s->row->used[s->area]
30009 && ((s->row->fill_line_p
30010 && (s->hl == DRAW_NORMAL_TEXT
30011 || s->hl == DRAW_IMAGE_RAISED
30012 || s->hl == DRAW_IMAGE_SUNKEN))
30013 || s->hl == DRAW_MOUSE_FACE))
30014 s->extends_to_end_of_line_p = true;
30015
30016
30017
30018
30019 if (s->extends_to_end_of_line_p)
30020 s->background_width = last_x - s->x + 1;
30021 else
30022 {
30023 s->background_width = s->width;
30024 #ifdef HAVE_WINDOW_SYSTEM
30025 if (FRAME_WINDOW_P (s->f)
30026 && s->hl == DRAW_CURSOR
30027 && MATRIX_ROW (s->w->current_matrix,
30028 s->w->phys_cursor.vpos)->mouse_face_p
30029 && cursor_in_mouse_face_p (s->w))
30030 {
30031
30032
30033
30034
30035 struct glyph *g = s->first_glyph;
30036 struct face *regular_face = FACE_FROM_ID (s->f, g->face_id);
30037 s->background_width +=
30038 adjust_glyph_width_for_mouse_face (g, s->row, s->w,
30039 regular_face, s->face);
30040
30041 s->width = s->background_width;
30042 }
30043 #endif
30044 }
30045 }
30046
30047
30048
30049
30050
30051 static struct glyph_string *
30052 glyph_string_containing_background_width (struct glyph_string *s)
30053 {
30054 if (s->cmp)
30055 while (s->cmp_from)
30056 s = s->prev;
30057
30058 return s;
30059 }
30060
30061
30062
30063
30064
30065
30066 static void
30067 compute_overhangs_and_x (struct glyph_string *s, int x, bool backward_p)
30068 {
30069 if (backward_p)
30070 {
30071 while (s)
30072 {
30073 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30074 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30075 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30076 x -= s->width;
30077 s->x = x;
30078 s = s->prev;
30079 }
30080 }
30081 else
30082 {
30083 while (s)
30084 {
30085 if (FRAME_RIF (s->f)->compute_glyph_string_overhangs)
30086 FRAME_RIF (s->f)->compute_glyph_string_overhangs (s);
30087 s->x = x;
30088 if (!s->cmp || s->cmp_to == s->cmp->glyph_len)
30089 x += s->width;
30090 s = s->next;
30091 }
30092 }
30093 }
30094
30095
30096
30097
30098
30099
30100
30101
30102
30103 #ifdef HAVE_NTGUI
30104
30105
30106 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30107 init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
30108 #else
30109 #define INIT_GLYPH_STRING(s, char2b, w, row, area, start, hl) \
30110 init_glyph_string (s, char2b, w, row, area, start, hl)
30111 #endif
30112
30113
30114
30115
30116
30117
30118
30119
30120
30121
30122
30123 #define BUILD_STRETCH_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30124 do \
30125 { \
30126 s = alloca (sizeof *s); \
30127 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30128 START = fill_stretch_glyph_string (s, START, END); \
30129 append_glyph_string (&HEAD, &TAIL, s); \
30130 s->x = (X); \
30131 } \
30132 while (false)
30133
30134
30135
30136
30137
30138
30139
30140
30141
30142
30143 #define BUILD_IMAGE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30144 do \
30145 { \
30146 s = alloca (sizeof *s); \
30147 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30148 fill_image_glyph_string (s); \
30149 append_glyph_string (&HEAD, &TAIL, s); \
30150 ++START; \
30151 s->x = (X); \
30152 } \
30153 while (false)
30154
30155 #ifndef HAVE_XWIDGETS
30156 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30157 eassume (false)
30158 #else
30159 # define BUILD_XWIDGET_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30160 do \
30161 { \
30162 s = alloca (sizeof *s); \
30163 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30164 fill_xwidget_glyph_string (s); \
30165 append_glyph_string (&(HEAD), &(TAIL), s); \
30166 ++(START); \
30167 s->x = (X); \
30168 } \
30169 while (false)
30170 #endif
30171
30172
30173
30174
30175
30176
30177
30178
30179
30180
30181 #define BUILD_CHAR_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30182 do \
30183 { \
30184 int face_id; \
30185 unsigned *char2b; \
30186 \
30187 face_id = (row)->glyphs[area][START].face_id; \
30188 \
30189 s = alloca (sizeof *s); \
30190 SAFE_NALLOCA (char2b, 1, (END) - (START)); \
30191 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30192 append_glyph_string (&HEAD, &TAIL, s); \
30193 s->x = (X); \
30194 START = fill_glyph_string (s, face_id, START, END, overlaps); \
30195 } \
30196 while (false)
30197
30198
30199
30200
30201
30202
30203
30204
30205
30206
30207
30208 #define BUILD_COMPOSITE_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30209 do { \
30210 int face_id = (row)->glyphs[area][START].face_id; \
30211 struct face *base_face = FACE_FROM_ID (f, face_id); \
30212 ptrdiff_t cmp_id = (row)->glyphs[area][START].u.cmp.id; \
30213 struct composition *cmp = composition_table[cmp_id]; \
30214 unsigned *char2b; \
30215 struct glyph_string *first_s = NULL; \
30216 int n; \
30217 \
30218 SAFE_NALLOCA (char2b, 1, cmp->glyph_len); \
30219 \
30220
30221 \
30222 for (n = 0; n < cmp->glyph_len;) \
30223 { \
30224 s = alloca (sizeof *s); \
30225 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30226 append_glyph_string (&(HEAD), &(TAIL), s); \
30227 s->cmp = cmp; \
30228 s->cmp_from = n; \
30229 s->x = (X); \
30230 if (n == 0) \
30231 first_s = s; \
30232 n = fill_composite_glyph_string (s, base_face, overlaps); \
30233 } \
30234 \
30235 ++START; \
30236 s = first_s; \
30237 } while (false)
30238
30239
30240
30241
30242
30243 #define BUILD_GSTRING_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30244 do { \
30245 int face_id; \
30246 unsigned *char2b; \
30247 Lisp_Object gstring; \
30248 \
30249 face_id = (row)->glyphs[area][START].face_id; \
30250 gstring = (composition_gstring_from_id \
30251 ((row)->glyphs[area][START].u.cmp.id)); \
30252 s = alloca (sizeof *s); \
30253 SAFE_NALLOCA (char2b, 1, LGSTRING_GLYPH_LEN (gstring)); \
30254 INIT_GLYPH_STRING (s, char2b, w, row, area, START, HL); \
30255 append_glyph_string (&(HEAD), &(TAIL), s); \
30256 s->x = (X); \
30257 START = fill_gstring_glyph_string (s, face_id, START, END, overlaps); \
30258 } while (false)
30259
30260
30261
30262
30263
30264
30265 #define BUILD_GLYPHLESS_GLYPH_STRING(START, END, HEAD, TAIL, HL, X, LAST_X) \
30266 do \
30267 { \
30268 int face_id; \
30269 \
30270 face_id = (row)->glyphs[area][START].face_id; \
30271 \
30272 s = alloca (sizeof *s); \
30273 INIT_GLYPH_STRING (s, NULL, w, row, area, START, HL); \
30274 append_glyph_string (&HEAD, &TAIL, s); \
30275 s->x = (X); \
30276 START = fill_glyphless_glyph_string (s, face_id, START, END, \
30277 overlaps); \
30278 } \
30279 while (false)
30280
30281
30282
30283
30284
30285
30286
30287
30288
30289
30290
30291
30292 #define BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30293 do \
30294 { \
30295 HEAD = TAIL = NULL; \
30296 while (START < END) \
30297 { \
30298 struct glyph *first_glyph = (row)->glyphs[area] + START; \
30299 switch (first_glyph->type) \
30300 { \
30301 case CHAR_GLYPH: \
30302 BUILD_CHAR_GLYPH_STRINGS (START, END, HEAD, TAIL, \
30303 HL, X, LAST_X); \
30304 break; \
30305 \
30306 case COMPOSITE_GLYPH: \
30307 if (first_glyph->u.cmp.automatic) \
30308 BUILD_GSTRING_GLYPH_STRING (START, END, HEAD, TAIL, \
30309 HL, X, LAST_X); \
30310 else \
30311 BUILD_COMPOSITE_GLYPH_STRING (START, END, HEAD, TAIL, \
30312 HL, X, LAST_X); \
30313 break; \
30314 \
30315 case STRETCH_GLYPH: \
30316 BUILD_STRETCH_GLYPH_STRING (START, END, HEAD, TAIL, \
30317 HL, X, LAST_X); \
30318 break; \
30319 \
30320 case IMAGE_GLYPH: \
30321 BUILD_IMAGE_GLYPH_STRING (START, END, HEAD, TAIL, \
30322 HL, X, LAST_X); \
30323 break;
30324
30325 #define BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30326 case XWIDGET_GLYPH: \
30327 BUILD_XWIDGET_GLYPH_STRING (START, END, HEAD, TAIL, \
30328 HL, X, LAST_X); \
30329 break;
30330
30331 #define BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X) \
30332 case GLYPHLESS_GLYPH: \
30333 BUILD_GLYPHLESS_GLYPH_STRING (START, END, HEAD, TAIL, \
30334 HL, X, LAST_X); \
30335 break; \
30336 \
30337 default: \
30338 emacs_abort (); \
30339 } \
30340 \
30341 if (s) \
30342 { \
30343 set_glyph_string_background_width (s, START, LAST_X); \
30344 (X) += s->width; \
30345 } \
30346 } \
30347 } while (false)
30348
30349
30350 #define BUILD_GLYPH_STRINGS(START, END, HEAD, TAIL, HL, X, LAST_X) \
30351 BUILD_GLYPH_STRINGS_1(START, END, HEAD, TAIL, HL, X, LAST_X) \
30352 BUILD_GLYPH_STRINGS_XW(START, END, HEAD, TAIL, HL, X, LAST_X) \
30353 BUILD_GLYPH_STRINGS_2(START, END, HEAD, TAIL, HL, X, LAST_X)
30354
30355
30356
30357
30358
30359
30360
30361
30362
30363
30364
30365
30366
30367
30368
30369
30370
30371
30372
30373
30374
30375
30376
30377
30378 static int
30379 draw_glyphs (struct window *w, int x, struct glyph_row *row,
30380 enum glyph_row_area area, ptrdiff_t start, ptrdiff_t end,
30381 enum draw_glyphs_face hl, int overlaps)
30382 {
30383 struct glyph_string *head, *tail;
30384 struct glyph_string *s;
30385 struct glyph_string *clip_head = NULL, *clip_tail = NULL;
30386 int i, j, x_reached, last_x, area_left = 0;
30387 struct frame *f = XFRAME (WINDOW_FRAME (w));
30388
30389 ALLOCATE_HDC (hdc, f);
30390
30391
30392 end = min (end, row->used[area]);
30393 start = clip_to_bounds (0, start, end);
30394
30395
30396
30397 if (row->full_width_p)
30398 {
30399
30400
30401 area_left = WINDOW_LEFT_EDGE_X (w);
30402 last_x = (WINDOW_LEFT_EDGE_X (w) + WINDOW_PIXEL_WIDTH (w)
30403 - (row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
30404 }
30405 else
30406 {
30407 area_left = window_box_left (w, area);
30408 last_x = area_left + window_box_width (w, area);
30409 }
30410 x += area_left;
30411
30412
30413
30414
30415
30416 i = start;
30417 USE_SAFE_ALLOCA;
30418 BUILD_GLYPH_STRINGS (i, end, head, tail, hl, x, last_x);
30419 if (tail)
30420 {
30421 s = glyph_string_containing_background_width (tail);
30422 x_reached = s->x + s->background_width;
30423 }
30424 else
30425 x_reached = x;
30426
30427
30428
30429
30430 if (head && !overlaps && row->contains_overlapping_glyphs_p)
30431 {
30432 struct glyph_string *h, *t;
30433 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
30434 int mouse_beg_col UNINIT, mouse_end_col UNINIT;
30435 bool check_mouse_face = false;
30436 int dummy_x = 0;
30437
30438
30439
30440 if (area == TEXT_AREA && row->mouse_face_p
30441 && hlinfo->mouse_face_beg_row >= 0
30442 && hlinfo->mouse_face_end_row >= 0)
30443 {
30444 ptrdiff_t row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
30445
30446 if (row_vpos >= hlinfo->mouse_face_beg_row
30447 && row_vpos <= hlinfo->mouse_face_end_row)
30448 {
30449 check_mouse_face = true;
30450 mouse_beg_col = (row_vpos == hlinfo->mouse_face_beg_row)
30451 ? hlinfo->mouse_face_beg_col : 0;
30452 mouse_end_col = (row_vpos == hlinfo->mouse_face_end_row)
30453 ? hlinfo->mouse_face_end_col
30454 : row->used[TEXT_AREA];
30455 }
30456 }
30457
30458
30459 if (FRAME_RIF (f)->compute_glyph_string_overhangs)
30460 for (s = head; s; s = s->next)
30461 FRAME_RIF (f)->compute_glyph_string_overhangs (s);
30462
30463
30464
30465
30466
30467
30468 i = left_overwritten (head);
30469 if (i >= 0)
30470 {
30471 enum draw_glyphs_face overlap_hl;
30472
30473
30474
30475
30476
30477
30478
30479
30480 if (check_mouse_face
30481 && mouse_beg_col < start && mouse_end_col > i)
30482 overlap_hl = DRAW_MOUSE_FACE;
30483 else
30484 overlap_hl = DRAW_NORMAL_TEXT;
30485
30486 if (hl != overlap_hl)
30487 clip_head = head;
30488 j = i;
30489 BUILD_GLYPH_STRINGS (j, start, h, t,
30490 overlap_hl, dummy_x, last_x);
30491 start = i;
30492 compute_overhangs_and_x (t, head->x, true);
30493 prepend_glyph_string_lists (&head, &tail, h, t);
30494 if (clip_head == NULL)
30495 clip_head = head;
30496 }
30497
30498
30499
30500
30501
30502
30503
30504
30505 i = left_overwriting (head);
30506 if (i >= 0)
30507 {
30508 enum draw_glyphs_face overlap_hl;
30509
30510 if (check_mouse_face
30511 && mouse_beg_col < start && mouse_end_col > i)
30512 overlap_hl = DRAW_MOUSE_FACE;
30513 else
30514 overlap_hl = DRAW_NORMAL_TEXT;
30515
30516 if (hl == overlap_hl || clip_head == NULL)
30517 clip_head = head;
30518 BUILD_GLYPH_STRINGS (i, start, h, t,
30519 overlap_hl, dummy_x, last_x);
30520 for (s = h; s; s = s->next)
30521 s->background_filled_p = true;
30522 compute_overhangs_and_x (t, head->x, true);
30523 prepend_glyph_string_lists (&head, &tail, h, t);
30524 }
30525
30526
30527
30528
30529
30530 i = right_overwritten (tail);
30531 if (i >= 0)
30532 {
30533 enum draw_glyphs_face overlap_hl;
30534
30535 if (check_mouse_face
30536 && mouse_beg_col < i && mouse_end_col > end)
30537 overlap_hl = DRAW_MOUSE_FACE;
30538 else
30539 overlap_hl = DRAW_NORMAL_TEXT;
30540
30541 if (hl != overlap_hl)
30542 clip_tail = tail;
30543 BUILD_GLYPH_STRINGS (end, i, h, t,
30544 overlap_hl, x, last_x);
30545
30546
30547 compute_overhangs_and_x (h, tail->x + tail->width, false);
30548 append_glyph_string_lists (&head, &tail, h, t);
30549 if (clip_tail == NULL)
30550 clip_tail = tail;
30551 }
30552
30553
30554
30555
30556
30557
30558 i = right_overwriting (tail);
30559 if (i >= 0)
30560 {
30561 enum draw_glyphs_face overlap_hl;
30562 if (check_mouse_face
30563 && mouse_beg_col < i && mouse_end_col > end)
30564 overlap_hl = DRAW_MOUSE_FACE;
30565 else
30566 overlap_hl = DRAW_NORMAL_TEXT;
30567
30568 if (hl == overlap_hl || clip_tail == NULL)
30569 clip_tail = tail;
30570 i++;
30571 BUILD_GLYPH_STRINGS (end, i, h, t,
30572 overlap_hl, x, last_x);
30573 for (s = h; s; s = s->next)
30574 s->background_filled_p = true;
30575 compute_overhangs_and_x (h, tail->x + tail->width, false);
30576 append_glyph_string_lists (&head, &tail, h, t);
30577 }
30578 tail = glyph_string_containing_background_width (tail);
30579 if (clip_tail)
30580 clip_tail = glyph_string_containing_background_width (clip_tail);
30581 if (clip_head || clip_tail)
30582 for (s = head; s; s = s->next)
30583 {
30584 s->clip_head = clip_head;
30585 s->clip_tail = clip_tail;
30586 }
30587 }
30588
30589
30590 for (s = head; s; s = s->next)
30591 FRAME_RIF (f)->draw_glyph_string (s);
30592
30593
30594
30595 if (area == TEXT_AREA
30596 && !row->full_width_p
30597
30598
30599
30600 && !overlaps)
30601 {
30602 int x0 = clip_head ? clip_head->x : (head ? head->x : x);
30603 int x1 = (clip_tail ? clip_tail->x + clip_tail->background_width
30604 : (tail ? tail->x + tail->background_width : x));
30605 x0 -= area_left;
30606 x1 -= area_left;
30607
30608 notice_overwritten_cursor (w, TEXT_AREA, x0, x1,
30609 row->y, MATRIX_ROW_BOTTOM_Y (row));
30610 }
30611
30612
30613
30614 if (row->full_width_p)
30615 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
30616 else
30617 x_reached -= area_left;
30618
30619 RELEASE_HDC (hdc, f);
30620
30621 SAFE_FREE ();
30622 return x_reached;
30623 }
30624
30625
30626
30627
30628
30629
30630
30631
30632 struct font *
30633 font_for_underline_metrics (struct glyph_string *s)
30634 {
30635 struct glyph *g0 = s->row->glyphs[s->area], *g;
30636
30637 for (g = s->first_glyph - 1; g >= g0; g--)
30638 {
30639 struct face *prev_face = FACE_FROM_ID (s->f, g->face_id);
30640 if (!(prev_face && prev_face->underline != FACE_NO_UNDERLINE))
30641 break;
30642 }
30643
30644
30645 if (g == s->first_glyph - 1)
30646 return s->font;
30647 else
30648 {
30649
30650
30651 return FACE_FROM_ID (s->f, g[1].face_id)->font;
30652 }
30653 }
30654
30655
30656
30657
30658 #define IT_EXPAND_MATRIX_WIDTH(it, area) \
30659 { \
30660 if (!it->f->fonts_changed \
30661 && (it->glyph_row->glyphs[area] \
30662 < it->glyph_row->glyphs[area + 1])) \
30663 { \
30664 it->w->ncols_scale_factor++; \
30665 it->f->fonts_changed = true; \
30666 } \
30667 }
30668
30669
30670
30671
30672 static void
30673 append_glyph (struct it *it)
30674 {
30675 struct glyph *glyph;
30676 enum glyph_row_area area = it->area;
30677
30678 eassert (it->glyph_row);
30679 eassert (it->char_to_display != '\n' && it->char_to_display != '\t');
30680
30681 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30682 if (glyph < it->glyph_row->glyphs[area + 1])
30683 {
30684
30685
30686 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30687 {
30688 struct glyph *g;
30689
30690
30691 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
30692 g[1] = *g;
30693 glyph = it->glyph_row->glyphs[area];
30694 }
30695 glyph->charpos = CHARPOS (it->position);
30696 glyph->object = it->object;
30697 if (it->pixel_width > 0)
30698 {
30699 eassert (it->pixel_width <= SHRT_MAX);
30700 glyph->pixel_width = it->pixel_width;
30701 glyph->padding_p = false;
30702 }
30703 else
30704 {
30705
30706
30707 glyph->pixel_width = 1;
30708 glyph->padding_p = true;
30709 }
30710 glyph->ascent = it->ascent;
30711 glyph->descent = it->descent;
30712 glyph->voffset = it->voffset;
30713 glyph->type = CHAR_GLYPH;
30714 glyph->avoid_cursor_p = it->avoid_cursor_p;
30715 glyph->multibyte_p = it->multibyte_p;
30716 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30717 {
30718
30719
30720 glyph->right_box_line_p = it->start_of_box_run_p;
30721 glyph->left_box_line_p = it->end_of_box_run_p;
30722 }
30723 else
30724 {
30725 glyph->left_box_line_p = it->start_of_box_run_p;
30726 glyph->right_box_line_p = it->end_of_box_run_p;
30727 }
30728 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30729 || it->phys_descent > it->descent);
30730 glyph->glyph_not_available_p = it->glyph_not_available_p;
30731 glyph->face_id = it->face_id;
30732 glyph->u.ch = it->char_to_display;
30733 glyph->slice.img = null_glyph_slice;
30734 glyph->font_type = FONT_TYPE_UNKNOWN;
30735 if (it->bidi_p)
30736 {
30737 glyph->resolved_level = it->bidi_it.resolved_level;
30738 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
30739 glyph->bidi_type = it->bidi_it.type;
30740 }
30741 else
30742 {
30743 glyph->resolved_level = 0;
30744 glyph->bidi_type = UNKNOWN_BT;
30745 }
30746 ++it->glyph_row->used[area];
30747 }
30748 else
30749 IT_EXPAND_MATRIX_WIDTH (it, area);
30750 }
30751
30752
30753
30754
30755 static void
30756 append_composite_glyph (struct it *it)
30757 {
30758 struct glyph *glyph;
30759 enum glyph_row_area area = it->area;
30760
30761 eassert (it->glyph_row);
30762
30763 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30764 if (glyph < it->glyph_row->glyphs[area + 1])
30765 {
30766
30767
30768 if (it->glyph_row->reversed_p && it->area == TEXT_AREA)
30769 {
30770 struct glyph *g;
30771
30772
30773 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
30774 g[1] = *g;
30775 glyph = it->glyph_row->glyphs[it->area];
30776 }
30777 glyph->charpos = it->cmp_it.charpos;
30778 glyph->object = it->object;
30779 eassert (it->pixel_width <= SHRT_MAX);
30780 glyph->pixel_width = it->pixel_width;
30781 glyph->ascent = it->ascent;
30782 glyph->descent = it->descent;
30783 glyph->voffset = it->voffset;
30784 glyph->type = COMPOSITE_GLYPH;
30785 if (it->cmp_it.ch < 0)
30786 {
30787 glyph->u.cmp.automatic = false;
30788 glyph->u.cmp.id = it->cmp_it.id;
30789 glyph->slice.cmp.from = glyph->slice.cmp.to = 0;
30790 }
30791 else
30792 {
30793 glyph->u.cmp.automatic = true;
30794 glyph->u.cmp.id = it->cmp_it.id;
30795 glyph->slice.cmp.from = it->cmp_it.from;
30796 glyph->slice.cmp.to = it->cmp_it.to - 1;
30797 }
30798 glyph->avoid_cursor_p = it->avoid_cursor_p;
30799 glyph->multibyte_p = it->multibyte_p;
30800 if (it->glyph_row->reversed_p && area == TEXT_AREA)
30801 {
30802
30803
30804 glyph->right_box_line_p = it->start_of_box_run_p;
30805 glyph->left_box_line_p = it->end_of_box_run_p;
30806 }
30807 else
30808 {
30809 glyph->left_box_line_p = it->start_of_box_run_p;
30810 glyph->right_box_line_p = it->end_of_box_run_p;
30811 }
30812 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
30813 || it->phys_descent > it->descent);
30814 glyph->padding_p = false;
30815 glyph->glyph_not_available_p = it->glyph_not_available_p;
30816 glyph->face_id = it->face_id;
30817 glyph->font_type = FONT_TYPE_UNKNOWN;
30818 if (it->bidi_p)
30819 {
30820 glyph->resolved_level = it->bidi_it.resolved_level;
30821 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
30822 glyph->bidi_type = it->bidi_it.type;
30823 }
30824 ++it->glyph_row->used[area];
30825 }
30826 else
30827 IT_EXPAND_MATRIX_WIDTH (it, area);
30828 }
30829
30830
30831
30832
30833
30834 static void
30835 take_vertical_position_into_account (struct it *it)
30836 {
30837 if (it->voffset)
30838 {
30839 if (it->voffset < 0)
30840
30841
30842 it->ascent -= it->voffset;
30843 else
30844
30845
30846 it->descent += it->voffset;
30847 }
30848 }
30849
30850
30851
30852
30853
30854
30855 static void
30856 produce_image_glyph (struct it *it)
30857 {
30858 struct image *img;
30859 struct face *face;
30860 int glyph_ascent, crop;
30861 struct glyph_slice slice;
30862
30863 eassert (it->what == IT_IMAGE);
30864
30865 face = FACE_FROM_ID (it->f, it->face_id);
30866
30867 prepare_face_for_display (it->f, face);
30868
30869 if (it->image_id < 0)
30870 {
30871
30872 it->ascent = it->phys_ascent = 0;
30873 it->descent = it->phys_descent = 0;
30874 it->pixel_width = 0;
30875 it->nglyphs = 0;
30876 return;
30877 }
30878
30879 img = IMAGE_FROM_ID (it->f, it->image_id);
30880
30881 prepare_image_for_display (it->f, img);
30882
30883 slice.x = slice.y = 0;
30884 slice.width = img->width;
30885 slice.height = img->height;
30886
30887 if (FIXNUMP (it->slice.x))
30888 slice.x = XFIXNUM (it->slice.x);
30889 else if (FLOATP (it->slice.x))
30890 slice.x = XFLOAT_DATA (it->slice.x) * img->width;
30891
30892 if (FIXNUMP (it->slice.y))
30893 slice.y = XFIXNUM (it->slice.y);
30894 else if (FLOATP (it->slice.y))
30895 slice.y = XFLOAT_DATA (it->slice.y) * img->height;
30896
30897 if (FIXNUMP (it->slice.width))
30898 slice.width = XFIXNUM (it->slice.width);
30899 else if (FLOATP (it->slice.width))
30900 slice.width = XFLOAT_DATA (it->slice.width) * img->width;
30901
30902 if (FIXNUMP (it->slice.height))
30903 slice.height = XFIXNUM (it->slice.height);
30904 else if (FLOATP (it->slice.height))
30905 slice.height = XFLOAT_DATA (it->slice.height) * img->height;
30906
30907 if (slice.x >= img->width)
30908 slice.x = img->width;
30909 if (slice.y >= img->height)
30910 slice.y = img->height;
30911 if (slice.x + slice.width >= img->width)
30912 slice.width = img->width - slice.x;
30913 if (slice.y + slice.height > img->height)
30914 slice.height = img->height - slice.y;
30915
30916 if (slice.width == 0 || slice.height == 0)
30917 return;
30918
30919 it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face, &slice);
30920
30921 it->descent = slice.height - glyph_ascent;
30922 if (slice.y == 0)
30923 it->descent += img->vmargin;
30924 if (slice.y + slice.height == img->height)
30925 it->descent += img->vmargin;
30926 it->phys_descent = it->descent;
30927
30928 it->pixel_width = slice.width;
30929 if (slice.x == 0)
30930 it->pixel_width += img->hmargin;
30931 if (slice.x + slice.width == img->width)
30932 it->pixel_width += img->hmargin;
30933
30934
30935
30936 if (it->descent < 0)
30937 it->descent = 0;
30938
30939 it->nglyphs = 1;
30940
30941 if (face->box != FACE_NO_BOX)
30942 {
30943
30944
30945 if (face->box_horizontal_line_width > 0)
30946 {
30947 if (slice.y == 0)
30948 it->ascent += face->box_horizontal_line_width;
30949 if (slice.y + slice.height == img->height)
30950 it->descent += face->box_horizontal_line_width;
30951 }
30952
30953 if (face->box_vertical_line_width > 0)
30954 {
30955 if (it->start_of_box_run_p && slice.x == 0)
30956 it->pixel_width += face->box_vertical_line_width;
30957 if (it->end_of_box_run_p && slice.x + slice.width == img->width)
30958 it->pixel_width += face->box_vertical_line_width;
30959 }
30960 }
30961
30962 take_vertical_position_into_account (it);
30963
30964
30965
30966 if ((crop = it->pixel_width - (it->last_visible_x - it->current_x), crop > 0)
30967 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
30968 {
30969 it->pixel_width -= crop;
30970 slice.width -= crop;
30971 }
30972
30973 if (it->glyph_row)
30974 {
30975 struct glyph *glyph;
30976 enum glyph_row_area area = it->area;
30977
30978 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
30979 if (it->glyph_row->reversed_p)
30980 {
30981 struct glyph *g;
30982
30983
30984 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
30985 g[1] = *g;
30986 glyph = it->glyph_row->glyphs[it->area];
30987 }
30988 if (glyph < it->glyph_row->glyphs[area + 1])
30989 {
30990 glyph->charpos = CHARPOS (it->position);
30991 glyph->object = it->object;
30992 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
30993 glyph->ascent = glyph_ascent;
30994 glyph->descent = it->descent;
30995 glyph->voffset = it->voffset;
30996 glyph->type = IMAGE_GLYPH;
30997 glyph->avoid_cursor_p = it->avoid_cursor_p;
30998 glyph->multibyte_p = it->multibyte_p;
30999 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31000 {
31001
31002
31003 glyph->right_box_line_p = it->start_of_box_run_p;
31004 glyph->left_box_line_p = it->end_of_box_run_p;
31005 }
31006 else
31007 {
31008 glyph->left_box_line_p = it->start_of_box_run_p;
31009 glyph->right_box_line_p = it->end_of_box_run_p;
31010 }
31011 glyph->overlaps_vertically_p = false;
31012 glyph->padding_p = false;
31013 glyph->glyph_not_available_p = false;
31014 glyph->face_id = it->face_id;
31015 glyph->u.img_id = img->id;
31016 glyph->slice.img = slice;
31017 glyph->font_type = FONT_TYPE_UNKNOWN;
31018 if (it->bidi_p)
31019 {
31020 glyph->resolved_level = it->bidi_it.resolved_level;
31021 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31022 glyph->bidi_type = it->bidi_it.type;
31023 }
31024 ++it->glyph_row->used[area];
31025 }
31026 else
31027 IT_EXPAND_MATRIX_WIDTH (it, area);
31028 }
31029 }
31030
31031 static void
31032 produce_xwidget_glyph (struct it *it)
31033 {
31034 #ifdef HAVE_XWIDGETS
31035 struct xwidget *xw;
31036 int glyph_ascent, crop;
31037 eassert (it->what == IT_XWIDGET);
31038
31039 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31040
31041 prepare_face_for_display (it->f, face);
31042
31043 xw = it->xwidget;
31044 it->ascent = it->phys_ascent = glyph_ascent = xw->height/2;
31045 it->descent = xw->height/2;
31046 it->phys_descent = it->descent;
31047 it->pixel_width = xw->width;
31048
31049
31050 if (it->descent < 0)
31051 it->descent = 0;
31052
31053 it->nglyphs = 1;
31054
31055 if (face->box != FACE_NO_BOX)
31056 {
31057 if (face->box_horizontal_line_width > 0)
31058 {
31059 it->ascent += face->box_horizontal_line_width;
31060 it->descent += face->box_horizontal_line_width;
31061 }
31062
31063 if (face->box_vertical_line_width > 0)
31064 {
31065 if (it->start_of_box_run_p)
31066 it->pixel_width += face->box_vertical_line_width;
31067 it->pixel_width += face->box_vertical_line_width;
31068 }
31069 }
31070
31071 take_vertical_position_into_account (it);
31072
31073
31074
31075 crop = it->pixel_width - (it->last_visible_x - it->current_x);
31076 if (crop > 0 && (it->hpos == 0 || it->pixel_width > it->last_visible_x / 4))
31077 it->pixel_width -= crop;
31078
31079 if (it->glyph_row)
31080 {
31081 enum glyph_row_area area = it->area;
31082 struct glyph *glyph
31083 = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31084
31085 if (it->glyph_row->reversed_p)
31086 {
31087 struct glyph *g;
31088
31089
31090 for (g = glyph - 1; g >= it->glyph_row->glyphs[it->area]; g--)
31091 g[1] = *g;
31092 glyph = it->glyph_row->glyphs[it->area];
31093 }
31094 if (glyph < it->glyph_row->glyphs[area + 1])
31095 {
31096 glyph->charpos = CHARPOS (it->position);
31097 glyph->object = it->object;
31098 glyph->pixel_width = clip_to_bounds (-1, it->pixel_width, SHRT_MAX);
31099 glyph->ascent = glyph_ascent;
31100 glyph->descent = it->descent;
31101 glyph->voffset = it->voffset;
31102 glyph->type = XWIDGET_GLYPH;
31103 glyph->avoid_cursor_p = it->avoid_cursor_p;
31104 glyph->multibyte_p = it->multibyte_p;
31105 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31106 {
31107
31108
31109 glyph->right_box_line_p = it->start_of_box_run_p;
31110 glyph->left_box_line_p = it->end_of_box_run_p;
31111 }
31112 else
31113 {
31114 glyph->left_box_line_p = it->start_of_box_run_p;
31115 glyph->right_box_line_p = it->end_of_box_run_p;
31116 }
31117 glyph->overlaps_vertically_p = 0;
31118 glyph->padding_p = 0;
31119 glyph->glyph_not_available_p = 0;
31120 glyph->face_id = it->face_id;
31121 glyph->u.xwidget = it->xwidget->xwidget_id;
31122 glyph->font_type = FONT_TYPE_UNKNOWN;
31123 if (it->bidi_p)
31124 {
31125 glyph->resolved_level = it->bidi_it.resolved_level;
31126 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31127 glyph->bidi_type = it->bidi_it.type;
31128 }
31129 ++it->glyph_row->used[area];
31130 }
31131 else
31132 IT_EXPAND_MATRIX_WIDTH (it, area);
31133 }
31134 #endif
31135 }
31136
31137
31138
31139
31140
31141 static void
31142 append_stretch_glyph (struct it *it, Lisp_Object object,
31143 int width, int height, int ascent)
31144 {
31145 struct glyph *glyph;
31146 enum glyph_row_area area = it->area;
31147
31148 eassert (ascent >= 0 && ascent <= height);
31149
31150 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31151 if (glyph < it->glyph_row->glyphs[area + 1])
31152 {
31153
31154
31155 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31156 {
31157 struct glyph *g;
31158
31159
31160 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31161 g[1] = *g;
31162 glyph = it->glyph_row->glyphs[area];
31163
31164
31165
31166
31167
31168
31169
31170
31171
31172
31173
31174
31175
31176
31177
31178 if (it->current_x < it->first_visible_x)
31179 width -= it->first_visible_x - it->current_x;
31180 eassert (width > 0);
31181 }
31182 glyph->charpos = CHARPOS (it->position);
31183 glyph->object = object;
31184
31185
31186 glyph->pixel_width = clip_to_bounds (-1, width, SHRT_MAX);
31187 glyph->ascent = ascent;
31188 glyph->descent = height - ascent;
31189 glyph->voffset = it->voffset;
31190 glyph->type = STRETCH_GLYPH;
31191 glyph->avoid_cursor_p = it->avoid_cursor_p;
31192 glyph->multibyte_p = it->multibyte_p;
31193 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31194 {
31195
31196
31197 glyph->right_box_line_p = it->start_of_box_run_p;
31198 glyph->left_box_line_p = it->end_of_box_run_p;
31199 }
31200 else
31201 {
31202 glyph->left_box_line_p = it->start_of_box_run_p;
31203 glyph->right_box_line_p = it->end_of_box_run_p;
31204 }
31205 glyph->overlaps_vertically_p = false;
31206 glyph->padding_p = false;
31207 glyph->glyph_not_available_p = false;
31208 glyph->face_id = it->face_id;
31209 glyph->u.stretch.ascent = ascent;
31210 glyph->u.stretch.height = height;
31211 glyph->slice.img = null_glyph_slice;
31212 glyph->font_type = FONT_TYPE_UNKNOWN;
31213 if (it->bidi_p)
31214 {
31215 glyph->resolved_level = it->bidi_it.resolved_level;
31216 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31217 glyph->bidi_type = it->bidi_it.type;
31218 }
31219 else
31220 {
31221 glyph->resolved_level = 0;
31222 glyph->bidi_type = UNKNOWN_BT;
31223 }
31224 ++it->glyph_row->used[area];
31225 }
31226 else
31227 IT_EXPAND_MATRIX_WIDTH (it, area);
31228 }
31229
31230 #endif
31231
31232
31233
31234
31235
31236
31237
31238
31239
31240
31241
31242
31243
31244
31245
31246
31247
31248
31249
31250
31251
31252
31253
31254
31255
31256
31257
31258
31259
31260
31261
31262
31263 void
31264 produce_stretch_glyph (struct it *it)
31265 {
31266
31267 Lisp_Object prop, plist;
31268 int width = 0, height = 0, align_to = -1;
31269 bool zero_width_ok_p = false;
31270 double tem;
31271 struct font *font = NULL;
31272
31273 #ifdef HAVE_WINDOW_SYSTEM
31274 int ascent = 0;
31275 bool zero_height_ok_p = false;
31276 struct face *face = NULL;
31277
31278 if (FRAME_WINDOW_P (it->f))
31279 {
31280 face = FACE_FROM_ID (it->f, it->face_id);
31281 font = face->font ? face->font : FRAME_FONT (it->f);
31282 prepare_face_for_display (it->f, face);
31283 }
31284 #endif
31285
31286
31287 eassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
31288 plist = XCDR (it->object);
31289
31290
31291 if ((prop = plist_get (plist, QCwidth), !NILP (prop))
31292 && calc_pixel_width_or_height (&tem, it, prop, font, true, NULL))
31293 {
31294
31295 zero_width_ok_p = true;
31296 width = (int)tem;
31297 }
31298 else if (prop = plist_get (plist, QCrelative_width), NUMVAL (prop) > 0)
31299 {
31300
31301
31302
31303 struct it it2;
31304 Lisp_Object object =
31305 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31306 unsigned char *p = (STRINGP (object)
31307 ? SDATA (object) + IT_STRING_BYTEPOS (*it)
31308 : BYTE_POS_ADDR (IT_BYTEPOS (*it)));
31309 bool multibyte_p =
31310 STRINGP (object) ? STRING_MULTIBYTE (object) : it->multibyte_p;
31311
31312 it2 = *it;
31313 if (multibyte_p)
31314 {
31315 it2.c = it2.char_to_display = string_char_and_length (p, &it2.len);
31316 #ifdef HAVE_WINDOW_SYSTEM
31317 if (FRAME_WINDOW_P (it->f) && ! ASCII_CHAR_P (it2.c))
31318 it2.face_id = FACE_FOR_CHAR (it->f, face, it2.c,
31319 IT_CHARPOS (*it),
31320 STRINGP (object)? object : Qnil);
31321 #endif
31322 }
31323 else
31324 {
31325 it2.c = it2.char_to_display = *p, it2.len = 1;
31326 if (! ASCII_CHAR_P (it2.c))
31327 it2.char_to_display = BYTE8_TO_CHAR (it2.c);
31328 }
31329
31330 it2.glyph_row = NULL;
31331 it2.what = IT_CHARACTER;
31332 PRODUCE_GLYPHS (&it2);
31333 width = NUMVAL (prop) * it2.pixel_width;
31334 }
31335 else if ((prop = plist_get (plist, QCalign_to), !NILP (prop))
31336 && calc_pixel_width_or_height (&tem, it, prop, font, true,
31337 &align_to))
31338 {
31339 int x = it->current_x + it->continuation_lines_width;
31340 int x0 = x;
31341
31342 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31343 {
31344 x -= it->lnum_pixel_width;
31345
31346 if (x + it->stretch_adjust >= it->first_visible_x)
31347 x += it->stretch_adjust;
31348 }
31349
31350 if (it->glyph_row == NULL || !it->glyph_row->mode_line_p)
31351 align_to = (align_to < 0
31352 ? 0
31353 : align_to - window_box_left_offset (it->w, TEXT_AREA));
31354 else if (align_to < 0)
31355 align_to = window_box_left_offset (it->w, TEXT_AREA);
31356 width = max (0, (int)tem + align_to - x);
31357
31358 int next_x = x + width;
31359 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
31360 {
31361
31362
31363 if (x < it->first_visible_x)
31364 {
31365 next_x -= it->first_visible_x - x;
31366 it->stretch_adjust = it->first_visible_x - x;
31367 }
31368 else
31369 next_x -= it->stretch_adjust;
31370 }
31371 width = next_x - x0;
31372 zero_width_ok_p = true;
31373 }
31374 else
31375
31376 width = FRAME_COLUMN_WIDTH (it->f);
31377
31378 if (width <= 0 && (width < 0 || !zero_width_ok_p))
31379 width = 1;
31380
31381 #ifdef HAVE_WINDOW_SYSTEM
31382
31383 if (FRAME_WINDOW_P (it->f))
31384 {
31385 int default_height = normal_char_height (font, ' ');
31386
31387 if ((prop = plist_get (plist, QCheight), !NILP (prop))
31388 && calc_pixel_width_or_height (&tem, it, prop, font, false, NULL))
31389 {
31390 height = (int)tem;
31391 zero_height_ok_p = true;
31392 }
31393 else if (prop = plist_get (plist, QCrelative_height),
31394 NUMVAL (prop) > 0)
31395 height = default_height * NUMVAL (prop);
31396 else
31397 height = default_height;
31398
31399 if (height <= 0 && (height < 0 || !zero_height_ok_p))
31400 height = 1;
31401
31402
31403
31404
31405 if (prop = plist_get (plist, QCascent),
31406 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
31407 ascent = height * NUMVAL (prop) / 100.0;
31408 else if (!NILP (prop)
31409 && calc_pixel_width_or_height (&tem, it, prop, font, false, 0))
31410 ascent = min (max (0, (int)tem), height);
31411 else
31412 ascent = (height * FONT_BASE (font)) / FONT_HEIGHT (font);
31413 }
31414 else
31415 #endif
31416 height = 1;
31417
31418 if (width > 0
31419 && it->area == TEXT_AREA && it->line_wrap != TRUNCATE
31420 && it->current_x + width > it->last_visible_x)
31421 {
31422 width = it->last_visible_x - it->current_x;
31423 #ifdef HAVE_WINDOW_SYSTEM
31424
31425
31426 width -= FRAME_WINDOW_P (it->f);
31427 #endif
31428 }
31429
31430 if (width > 0 && height > 0 && it->glyph_row)
31431 {
31432 Lisp_Object o_object = it->object;
31433 Lisp_Object object =
31434 it->sp > 0 ? it->stack[it->sp - 1].string : it->string;
31435 int n = width;
31436
31437 if (!STRINGP (object))
31438 object = it->w->contents;
31439 #ifdef HAVE_WINDOW_SYSTEM
31440 if (FRAME_WINDOW_P (it->f))
31441 append_stretch_glyph (it, object, width, height, ascent);
31442 else
31443 #endif
31444 {
31445 it->object = object;
31446 it->char_to_display = ' ';
31447 it->pixel_width = it->len = 1;
31448 while (n--)
31449 tty_append_glyph (it);
31450 it->object = o_object;
31451 }
31452 }
31453
31454 it->pixel_width = width;
31455 #ifdef HAVE_WINDOW_SYSTEM
31456 if (FRAME_WINDOW_P (it->f))
31457 {
31458 it->ascent = it->phys_ascent = ascent;
31459 it->descent = it->phys_descent = height - it->ascent;
31460 it->nglyphs = width > 0 && height > 0;
31461 take_vertical_position_into_account (it);
31462 }
31463 else
31464 #endif
31465 it->nglyphs = width;
31466 }
31467
31468
31469
31470
31471
31472
31473
31474 static void
31475 produce_special_glyphs (struct it *it, enum display_element_type what)
31476 {
31477 struct it temp_it;
31478 Lisp_Object gc;
31479 GLYPH glyph;
31480
31481 temp_it = *it;
31482 temp_it.object = Qnil;
31483 memset (&temp_it.current, 0, sizeof temp_it.current);
31484
31485 if (what == IT_CONTINUATION)
31486 {
31487
31488 if (it->bidi_it.paragraph_dir == R2L)
31489 SET_GLYPH_FROM_CHAR (glyph, '/');
31490 else
31491 SET_GLYPH_FROM_CHAR (glyph, '\\');
31492 if (it->dp
31493 && (gc = DISP_CONTINUE_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31494 {
31495
31496 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31497 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31498 }
31499 }
31500 else if (what == IT_TRUNCATION)
31501 {
31502
31503 SET_GLYPH_FROM_CHAR (glyph, '$');
31504 if (it->dp
31505 && (gc = DISP_TRUNC_GLYPH (it->dp), GLYPH_CODE_P (gc)))
31506 {
31507
31508 SET_GLYPH_FROM_GLYPH_CODE (glyph, gc);
31509 spec_glyph_lookup_face (XWINDOW (it->window), &glyph);
31510 }
31511 }
31512 else
31513 emacs_abort ();
31514
31515 #ifdef HAVE_WINDOW_SYSTEM
31516
31517
31518
31519
31520
31521 if (FRAME_WINDOW_P (temp_it.f)
31522
31523
31524
31525 && temp_it.glyph_row
31526
31527
31528
31529 && temp_it.glyph_row->used[TEXT_AREA] > 0
31530 && (temp_it.glyph_row->reversed_p
31531 ? WINDOW_LEFT_FRINGE_WIDTH (temp_it.w)
31532 : WINDOW_RIGHT_FRINGE_WIDTH (temp_it.w)) == 0)
31533 {
31534 int stretch_width = temp_it.last_visible_x - temp_it.current_x;
31535
31536 if (stretch_width > 0)
31537 {
31538 struct face *face = FACE_FROM_ID (temp_it.f, temp_it.face_id);
31539 struct font *font =
31540 face->font ? face->font : FRAME_FONT (temp_it.f);
31541 int stretch_ascent =
31542 (((temp_it.ascent + temp_it.descent)
31543 * FONT_BASE (font)) / FONT_HEIGHT (font));
31544
31545 append_stretch_glyph (&temp_it, Qnil, stretch_width,
31546 temp_it.ascent + temp_it.descent,
31547 stretch_ascent);
31548 }
31549 }
31550 #endif
31551
31552 temp_it.dp = NULL;
31553 temp_it.what = IT_CHARACTER;
31554 temp_it.c = temp_it.char_to_display = GLYPH_CHAR (glyph);
31555 temp_it.face_id = GLYPH_FACE (glyph);
31556 temp_it.len = CHAR_BYTES (temp_it.c);
31557
31558 PRODUCE_GLYPHS (&temp_it);
31559 it->pixel_width = temp_it.pixel_width;
31560 it->nglyphs = temp_it.nglyphs;
31561 }
31562
31563 #ifdef HAVE_WINDOW_SYSTEM
31564
31565
31566
31567
31568
31569
31570
31571
31572
31573 static Lisp_Object
31574 calc_line_height_property (struct it *it, Lisp_Object val, struct font *font,
31575 int boff, bool override)
31576 {
31577 Lisp_Object face_name = Qnil;
31578 int ascent, descent, height;
31579
31580 if (NILP (val) || INTEGERP (val) || (override && EQ (val, Qt)))
31581 return val;
31582
31583 if (CONSP (val))
31584 {
31585 face_name = XCAR (val);
31586 val = XCDR (val);
31587 if (!NUMBERP (val))
31588 val = make_fixnum (1);
31589 if (NILP (face_name))
31590 {
31591 height = it->ascent + it->descent;
31592 goto scale;
31593 }
31594 }
31595
31596 if (NILP (face_name))
31597 {
31598 font = FRAME_FONT (it->f);
31599 boff = FRAME_BASELINE_OFFSET (it->f);
31600 }
31601 else if (EQ (face_name, Qt))
31602 {
31603 override = false;
31604 }
31605 else
31606 {
31607 int face_id;
31608 struct face *face;
31609
31610 face_id = lookup_named_face (it->w, it->f, face_name, false);
31611 face = FACE_FROM_ID_OR_NULL (it->f, face_id);
31612 if (face == NULL || ((font = face->font) == NULL))
31613 return make_fixnum (-1);
31614 boff = font->baseline_offset;
31615 if (font->vertical_centering)
31616 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31617 }
31618
31619 normal_char_ascent_descent (font, -1, &ascent, &descent);
31620
31621 if (override)
31622 {
31623 it->override_ascent = ascent;
31624 it->override_descent = descent;
31625 it->override_boff = boff;
31626 }
31627
31628 height = ascent + descent;
31629
31630 scale:
31631
31632 if (FLOATP (val))
31633 height = (int)(XFLOAT_DATA (val) * height);
31634 else if (INTEGERP (val))
31635 {
31636 intmax_t v;
31637 if (integer_to_intmax (val, &v))
31638 height *= v;
31639 }
31640
31641 return make_fixnum (height);
31642 }
31643
31644
31645
31646
31647
31648
31649
31650
31651
31652
31653
31654
31655
31656
31657 static void
31658 append_glyphless_glyph (struct it *it, int face_id, bool for_no_font, int len,
31659 short upper_xoff, short upper_yoff,
31660 short lower_xoff, short lower_yoff)
31661 {
31662 struct glyph *glyph;
31663 enum glyph_row_area area = it->area;
31664
31665 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
31666 if (glyph < it->glyph_row->glyphs[area + 1])
31667 {
31668
31669
31670 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31671 {
31672 struct glyph *g;
31673
31674
31675 for (g = glyph - 1; g >= it->glyph_row->glyphs[area]; g--)
31676 g[1] = *g;
31677 glyph = it->glyph_row->glyphs[area];
31678 }
31679 glyph->charpos = CHARPOS (it->position);
31680 glyph->object = it->object;
31681 eassert (it->pixel_width <= SHRT_MAX);
31682 glyph->pixel_width = it->pixel_width;
31683 glyph->ascent = it->ascent;
31684 glyph->descent = it->descent;
31685 glyph->voffset = it->voffset;
31686 glyph->type = GLYPHLESS_GLYPH;
31687 glyph->u.glyphless.method = it->glyphless_method;
31688 glyph->u.glyphless.for_no_font = for_no_font;
31689 glyph->u.glyphless.len = len;
31690 glyph->u.glyphless.ch = it->c;
31691 glyph->slice.glyphless.upper_xoff = upper_xoff;
31692 glyph->slice.glyphless.upper_yoff = upper_yoff;
31693 glyph->slice.glyphless.lower_xoff = lower_xoff;
31694 glyph->slice.glyphless.lower_yoff = lower_yoff;
31695 glyph->avoid_cursor_p = it->avoid_cursor_p;
31696 glyph->multibyte_p = it->multibyte_p;
31697 if (it->glyph_row->reversed_p && area == TEXT_AREA)
31698 {
31699
31700
31701 glyph->right_box_line_p = it->start_of_box_run_p;
31702 glyph->left_box_line_p = it->end_of_box_run_p;
31703 }
31704 else
31705 {
31706 glyph->left_box_line_p = it->start_of_box_run_p;
31707 glyph->right_box_line_p = it->end_of_box_run_p;
31708 }
31709 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
31710 || it->phys_descent > it->descent);
31711 glyph->padding_p = false;
31712 glyph->glyph_not_available_p = false;
31713 glyph->face_id = face_id;
31714 glyph->font_type = FONT_TYPE_UNKNOWN;
31715 if (it->bidi_p)
31716 {
31717 glyph->resolved_level = it->bidi_it.resolved_level;
31718 eassert ((it->bidi_it.type & 7) == it->bidi_it.type);
31719 glyph->bidi_type = it->bidi_it.type;
31720 }
31721 ++it->glyph_row->used[area];
31722 }
31723 else
31724 IT_EXPAND_MATRIX_WIDTH (it, area);
31725 }
31726
31727
31728
31729
31730
31731
31732
31733
31734
31735
31736
31737 static void
31738 produce_glyphless_glyph (struct it *it, bool for_no_font, Lisp_Object acronym)
31739 {
31740 int face_id;
31741 struct face *face;
31742 struct font *font;
31743 int base_width, base_height, width, height;
31744 short upper_xoff, upper_yoff, lower_xoff, lower_yoff;
31745 int len;
31746
31747
31748
31749 face = FACE_FROM_ID (it->f, it->face_id)->ascii_face;
31750 font = face->font ? face->font : FRAME_FONT (it->f);
31751 normal_char_ascent_descent (font, -1, &it->ascent, &it->descent);
31752 it->ascent += font->baseline_offset;
31753 it->descent -= font->baseline_offset;
31754 base_height = it->ascent + it->descent;
31755 base_width = font->average_width;
31756
31757 face_id = merge_glyphless_glyph_face (it);
31758
31759 if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
31760 {
31761 it->pixel_width = THIN_SPACE_WIDTH;
31762 len = 0;
31763 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
31764 }
31765 else if (it->glyphless_method == GLYPHLESS_DISPLAY_EMPTY_BOX)
31766 {
31767 width = CHARACTER_WIDTH (it->c);
31768 if (width == 0)
31769 width = 1;
31770 else if (width > 4)
31771 width = 4;
31772 it->pixel_width = base_width * width;
31773 len = 0;
31774 upper_xoff = upper_yoff = lower_xoff = lower_yoff = 0;
31775 }
31776 else
31777 {
31778 char buf[7];
31779 const char *str;
31780 unsigned int code[6];
31781 int upper_len;
31782 int ascent, descent;
31783 struct font_metrics metrics_upper, metrics_lower;
31784
31785 face = FACE_FROM_ID (it->f, face_id);
31786 font = face->font ? face->font : FRAME_FONT (it->f);
31787 prepare_face_for_display (it->f, face);
31788
31789 if (it->glyphless_method == GLYPHLESS_DISPLAY_ACRONYM)
31790 {
31791 if (! STRINGP (acronym) && CHAR_TABLE_P (Vglyphless_char_display))
31792 acronym = CHAR_TABLE_REF (Vglyphless_char_display, it->c);
31793 if (CONSP (acronym))
31794 acronym = XCAR (acronym);
31795 str = STRINGP (acronym) ? SSDATA (acronym) : "";
31796 }
31797 else
31798 {
31799 eassert (it->glyphless_method == GLYPHLESS_DISPLAY_HEX_CODE);
31800 sprintf (buf, "%0*X", it->c < 0x10000 ? 4 : 6, it->c + 0u);
31801 str = buf;
31802 }
31803 for (len = 0; str[len] && ASCII_CHAR_P (str[len]) && len < 6; len++)
31804 code[len] = font->driver->encode_char (font, str[len]);
31805 upper_len = (len + 1) / 2;
31806 font->driver->text_extents (font, code, upper_len,
31807 &metrics_upper);
31808 font->driver->text_extents (font, code + upper_len, len - upper_len,
31809 &metrics_lower);
31810
31811
31812
31813
31814 width = max (metrics_upper.width, metrics_lower.width) + 4;
31815 upper_xoff = lower_xoff = 2;
31816 if (base_width >= width)
31817 {
31818
31819 it->pixel_width = base_width;
31820 lower_xoff = base_width - 2 - metrics_lower.width;
31821 }
31822 else
31823 {
31824
31825 it->pixel_width = width;
31826 if (metrics_upper.width >= metrics_lower.width)
31827 lower_xoff = (width - metrics_lower.width) / 2;
31828 else
31829 upper_xoff = (width - metrics_upper.width) / 2;
31830 }
31831
31832
31833
31834 height = (metrics_upper.ascent + metrics_upper.descent
31835 + metrics_lower.ascent + metrics_lower.descent) + 5;
31836
31837
31838
31839
31840
31841
31842
31843
31844 ascent = - (it->descent - (base_height + height + 1) / 2);
31845 descent = it->descent - (base_height - height) / 2;
31846 lower_yoff = descent - 2 - metrics_lower.descent;
31847 upper_yoff = (lower_yoff - metrics_lower.ascent - 1
31848 - metrics_upper.descent);
31849
31850 if (height > base_height)
31851 {
31852 it->ascent = ascent;
31853 it->descent = descent;
31854 }
31855 }
31856
31857 it->phys_ascent = it->ascent;
31858 it->phys_descent = it->descent;
31859 if (it->glyph_row)
31860 append_glyphless_glyph (it, face_id, for_no_font, len,
31861 upper_xoff, upper_yoff,
31862 lower_xoff, lower_yoff);
31863 it->nglyphs = 1;
31864 take_vertical_position_into_account (it);
31865 }
31866
31867
31868
31869
31870
31871 #define IT_APPLY_FACE_BOX(it, face) \
31872 do { \
31873 if (face->box != FACE_NO_BOX) \
31874 { \
31875 int thick = face->box_horizontal_line_width; \
31876 if (thick > 0) \
31877 { \
31878 it->ascent += thick; \
31879 it->descent += thick; \
31880 } \
31881 \
31882 thick = face->box_vertical_line_width; \
31883 if (thick > 0) \
31884 { \
31885 if (it->start_of_box_run_p) \
31886 it->pixel_width += thick; \
31887 if (it->end_of_box_run_p) \
31888 it->pixel_width += thick; \
31889 } \
31890 } \
31891 } while (false)
31892
31893
31894
31895
31896
31897
31898 void
31899 gui_produce_glyphs (struct it *it)
31900 {
31901 int extra_line_spacing = it->extra_line_spacing;
31902
31903 it->glyph_not_available_p = false;
31904
31905 if (it->what == IT_CHARACTER)
31906 {
31907 unsigned char2b;
31908 struct face *face = FACE_FROM_ID (it->f, it->face_id);
31909 struct font *font = face->font;
31910 struct font_metrics *pcm = NULL;
31911 int boff;
31912
31913 if (font == NULL)
31914 {
31915
31916
31917
31918 Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
31919
31920 eassert (it->what == IT_GLYPHLESS);
31921 produce_glyphless_glyph (it, true,
31922 STRINGP (acronym) ? acronym : Qnil);
31923 goto done;
31924 }
31925
31926 boff = font->baseline_offset;
31927 if (font->vertical_centering)
31928 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
31929
31930 if (it->char_to_display != '\n' && it->char_to_display != '\t')
31931 {
31932 it->nglyphs = 1;
31933
31934 if (it->override_ascent >= 0)
31935 {
31936 it->ascent = it->override_ascent;
31937 it->descent = it->override_descent;
31938 boff = it->override_boff;
31939 }
31940 else
31941 {
31942 it->ascent = FONT_BASE (font) + boff;
31943 it->descent = FONT_DESCENT (font) - boff;
31944 }
31945
31946 if (get_char_glyph_code (it->char_to_display, font, &char2b))
31947 {
31948 pcm = get_per_char_metric (font, &char2b);
31949 if (pcm->width == 0
31950 && pcm->rbearing == 0 && pcm->lbearing == 0)
31951 pcm = NULL;
31952 }
31953
31954 if (pcm)
31955 {
31956 it->phys_ascent = pcm->ascent + boff;
31957 it->phys_descent = pcm->descent - boff;
31958 it->pixel_width = pcm->width;
31959
31960
31961 if (it->override_ascent < 0)
31962 {
31963 if (FONT_TOO_HIGH (font))
31964 {
31965 it->ascent = it->phys_ascent;
31966 it->descent = it->phys_descent;
31967
31968
31969 if (it->ascent < 0)
31970 it->ascent = 0;
31971 if (it->descent < 0)
31972 it->descent = 0;
31973 }
31974 }
31975 }
31976 else
31977 {
31978 it->glyph_not_available_p = true;
31979 it->phys_ascent = it->ascent;
31980 it->phys_descent = it->descent;
31981 it->pixel_width = font->space_width;
31982 }
31983
31984 if (it->constrain_row_ascent_descent_p)
31985 {
31986 if (it->descent > it->max_descent)
31987 {
31988 it->ascent += it->descent - it->max_descent;
31989 it->descent = it->max_descent;
31990 }
31991 if (it->ascent > it->max_ascent)
31992 {
31993 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
31994 it->ascent = it->max_ascent;
31995 }
31996 it->phys_ascent = min (it->phys_ascent, it->ascent);
31997 it->phys_descent = min (it->phys_descent, it->descent);
31998 extra_line_spacing = 0;
31999 }
32000
32001
32002
32003 bool stretched_p
32004 = it->char_to_display == ' ' && !NILP (it->space_width);
32005 if (stretched_p)
32006 it->pixel_width *= XFLOATINT (it->space_width);
32007
32008 IT_APPLY_FACE_BOX(it, face);
32009
32010
32011
32012 if (face->overline_p)
32013 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32014
32015 if (it->constrain_row_ascent_descent_p)
32016 {
32017 if (it->ascent > it->max_ascent)
32018 it->ascent = it->max_ascent;
32019 if (it->descent > it->max_descent)
32020 it->descent = it->max_descent;
32021 }
32022
32023 take_vertical_position_into_account (it);
32024
32025
32026 if (it->glyph_row)
32027 {
32028 if (stretched_p)
32029 {
32030
32031
32032 int ascent = (((it->ascent + it->descent) * FONT_BASE (font))
32033 / FONT_HEIGHT (font));
32034 append_stretch_glyph (it, it->object, it->pixel_width,
32035 it->ascent + it->descent, ascent);
32036 }
32037 else
32038 append_glyph (it);
32039
32040
32041
32042
32043 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
32044 it->glyph_row->contains_overlapping_glyphs_p = true;
32045 }
32046 if (! stretched_p && it->pixel_width == 0)
32047
32048
32049 it->pixel_width = 1;
32050 }
32051 else if (it->char_to_display == '\n')
32052 {
32053
32054
32055
32056
32057 Lisp_Object height;
32058 Lisp_Object total_height = Qnil;
32059
32060 it->override_ascent = -1;
32061 it->pixel_width = 0;
32062 it->nglyphs = 0;
32063
32064 height = get_it_property (it, Qline_height);
32065
32066 if (CONSP (height)
32067 && CONSP (XCDR (height))
32068 && NILP (XCDR (XCDR (height))))
32069 {
32070 total_height = XCAR (XCDR (height));
32071 height = XCAR (height);
32072 }
32073 height = calc_line_height_property (it, height, font, boff, true);
32074
32075 if (it->override_ascent >= 0)
32076 {
32077 it->ascent = it->override_ascent;
32078 it->descent = it->override_descent;
32079 boff = it->override_boff;
32080 }
32081 else
32082 {
32083 if (FONT_TOO_HIGH (font))
32084 {
32085 it->ascent = font->pixel_size + boff - 1;
32086 it->descent = -boff + 1;
32087 if (it->descent < 0)
32088 it->descent = 0;
32089 }
32090 else
32091 {
32092 it->ascent = FONT_BASE (font) + boff;
32093 it->descent = FONT_DESCENT (font) - boff;
32094 }
32095 }
32096
32097 if (EQ (height, Qt))
32098 {
32099 if (it->descent > it->max_descent)
32100 {
32101 it->ascent += it->descent - it->max_descent;
32102 it->descent = it->max_descent;
32103 }
32104 if (it->ascent > it->max_ascent)
32105 {
32106 it->descent = min (it->max_descent, it->descent + it->ascent - it->max_ascent);
32107 it->ascent = it->max_ascent;
32108 }
32109 it->phys_ascent = min (it->phys_ascent, it->ascent);
32110 it->phys_descent = min (it->phys_descent, it->descent);
32111 it->constrain_row_ascent_descent_p = true;
32112 extra_line_spacing = 0;
32113 }
32114 else
32115 {
32116 Lisp_Object spacing;
32117
32118 it->phys_ascent = it->ascent;
32119 it->phys_descent = it->descent;
32120
32121 if ((it->max_ascent > 0 || it->max_descent > 0)
32122 && face->box != FACE_NO_BOX
32123 && face->box_horizontal_line_width > 0)
32124 {
32125 it->ascent += face->box_horizontal_line_width;
32126 it->descent += face->box_horizontal_line_width;
32127 }
32128 if (!NILP (height)
32129 && XFIXNUM (height) > it->ascent + it->descent)
32130 it->ascent = XFIXNUM (height) - it->descent;
32131
32132 if (!NILP (total_height))
32133 spacing = calc_line_height_property (it, total_height, font,
32134 boff, false);
32135 else
32136 {
32137 spacing = get_it_property (it, Qline_spacing);
32138 spacing = calc_line_height_property (it, spacing, font,
32139 boff, false);
32140 }
32141 if (FIXNUMP (spacing))
32142 {
32143 extra_line_spacing = XFIXNUM (spacing);
32144 if (!NILP (total_height))
32145 extra_line_spacing -= (it->phys_ascent + it->phys_descent);
32146 }
32147 }
32148 }
32149 else
32150 {
32151 if (font->space_width > 0)
32152 {
32153 int tab_width = it->tab_width * font->space_width;
32154 int x = it->current_x + it->continuation_lines_width;
32155 int x0 = x;
32156
32157 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32158 {
32159 x -= it->lnum_pixel_width;
32160
32161 if (x + it->stretch_adjust >= it->first_visible_x)
32162 x += it->stretch_adjust;
32163 }
32164
32165 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
32166
32167
32168
32169
32170 if (next_tab_x - x < font->space_width)
32171 next_tab_x += tab_width;
32172 if (!NILP (Vdisplay_line_numbers) && it->line_number_produced_p)
32173 {
32174 next_tab_x += it->lnum_pixel_width;
32175
32176
32177 if (x < it->first_visible_x)
32178 {
32179 next_tab_x -= it->first_visible_x - x;
32180 it->stretch_adjust = it->first_visible_x - x;
32181 }
32182 else
32183 next_tab_x -= it->stretch_adjust;
32184 }
32185
32186 it->pixel_width = next_tab_x - x0;
32187 it->nglyphs = 1;
32188 if (FONT_TOO_HIGH (font))
32189 {
32190 if (get_char_glyph_code (' ', font, &char2b))
32191 {
32192 pcm = get_per_char_metric (font, &char2b);
32193 if (pcm->width == 0
32194 && pcm->rbearing == 0 && pcm->lbearing == 0)
32195 pcm = NULL;
32196 }
32197
32198 if (pcm)
32199 {
32200 it->ascent = pcm->ascent + boff;
32201 it->descent = pcm->descent - boff;
32202 }
32203 else
32204 {
32205 it->ascent = font->pixel_size + boff - 1;
32206 it->descent = -boff + 1;
32207 }
32208 if (it->ascent < 0)
32209 it->ascent = 0;
32210 if (it->descent < 0)
32211 it->descent = 0;
32212 }
32213 else
32214 {
32215 it->ascent = FONT_BASE (font) + boff;
32216 it->descent = FONT_DESCENT (font) - boff;
32217 }
32218 it->phys_ascent = it->ascent;
32219 it->phys_descent = it->descent;
32220
32221 if (it->glyph_row)
32222 {
32223 append_stretch_glyph (it, it->object, it->pixel_width,
32224 it->ascent + it->descent, it->ascent);
32225 }
32226 }
32227 else
32228 {
32229 it->pixel_width = 0;
32230 it->nglyphs = 1;
32231 }
32232 }
32233
32234 if (FONT_TOO_HIGH (font))
32235 {
32236 int font_ascent, font_descent;
32237
32238
32239
32240
32241
32242
32243
32244
32245 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32246 it->max_ascent = max (it->max_ascent, font_ascent);
32247 it->max_descent = max (it->max_descent, font_descent);
32248 }
32249
32250 if (it->ascent < 0)
32251 it->ascent = 0;
32252 if (it->descent < 0)
32253 it->descent = 0;
32254 }
32255 else if (it->what == IT_COMPOSITION && it->cmp_it.ch < 0)
32256 {
32257
32258
32259
32260
32261
32262
32263
32264
32265 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32266 int boff;
32267 struct composition *cmp = composition_table[it->cmp_it.id];
32268 int glyph_len = cmp->glyph_len;
32269 struct font *font = face->font;
32270
32271 it->nglyphs = 1;
32272
32273
32274
32275
32276
32277
32278
32279
32280 if (! cmp->font || cmp->font != font)
32281 {
32282
32283
32284
32285
32286 int font_ascent, font_descent, font_height;
32287
32288 int leftmost, rightmost, lowest, highest;
32289 int lbearing, rbearing;
32290 int i, width, ascent, descent;
32291 int c;
32292 unsigned char2b;
32293 struct font_metrics *pcm;
32294 ptrdiff_t pos;
32295
32296 eassume (0 < glyph_len);
32297 do
32298 c = COMPOSITION_GLYPH (cmp, glyph_len - 1);
32299 while (c == '\t' && 0 < --glyph_len);
32300
32301 bool right_padded = glyph_len < cmp->glyph_len;
32302 for (i = 0; i < glyph_len; i++)
32303 {
32304 c = COMPOSITION_GLYPH (cmp, i);
32305 if (c != '\t')
32306 break;
32307 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32308 }
32309 bool left_padded = i > 0;
32310
32311 pos = (STRINGP (it->string) ? IT_STRING_CHARPOS (*it)
32312 : IT_CHARPOS (*it));
32313
32314 bool font_not_found_p = font == NULL;
32315 if (font_not_found_p)
32316 {
32317 face = face->ascii_face;
32318 font = face->font;
32319 }
32320 boff = font->baseline_offset;
32321 if (font->vertical_centering)
32322 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
32323 normal_char_ascent_descent (font, -1, &font_ascent, &font_descent);
32324 font_ascent += boff;
32325 font_descent -= boff;
32326 font_height = font_ascent + font_descent;
32327
32328 cmp->font = font;
32329
32330 pcm = NULL;
32331 if (! font_not_found_p)
32332 {
32333 get_char_face_and_encoding (it->f, c, it->face_id,
32334 &char2b, false);
32335 pcm = get_per_char_metric (font, &char2b);
32336 }
32337
32338
32339 if (pcm)
32340 {
32341 width = cmp->glyph_len > 0 ? pcm->width : 0;
32342 ascent = pcm->ascent;
32343 descent = pcm->descent;
32344 lbearing = pcm->lbearing;
32345 rbearing = pcm->rbearing;
32346 }
32347 else
32348 {
32349 width = cmp->glyph_len > 0 ? font->space_width : 0;
32350 ascent = FONT_BASE (font);
32351 descent = FONT_DESCENT (font);
32352 lbearing = 0;
32353 rbearing = width;
32354 }
32355
32356 rightmost = width;
32357 leftmost = 0;
32358 lowest = - descent + boff;
32359 highest = ascent + boff;
32360
32361 if (! font_not_found_p
32362 && font->default_ascent
32363 && CHAR_TABLE_P (Vuse_default_ascent)
32364 && !NILP (Faref (Vuse_default_ascent,
32365 make_fixnum (it->char_to_display))))
32366 highest = font->default_ascent + boff;
32367
32368
32369
32370
32371 cmp->offsets[i * 2] = 0;
32372 cmp->offsets[i * 2 + 1] = boff;
32373 cmp->lbearing = lbearing;
32374 cmp->rbearing = rbearing;
32375
32376
32377 for (i++; i < glyph_len; i++)
32378 {
32379 int left, right, btm, top;
32380 int ch = COMPOSITION_GLYPH (cmp, i);
32381 int face_id;
32382 struct face *this_face;
32383
32384 if (ch == '\t')
32385 ch = ' ';
32386 face_id = FACE_FOR_CHAR (it->f, face, ch, pos, it->string);
32387 this_face = FACE_FROM_ID (it->f, face_id);
32388 font = this_face->font;
32389
32390 if (font == NULL)
32391 pcm = NULL;
32392 else
32393 {
32394 get_char_face_and_encoding (it->f, ch, face_id,
32395 &char2b, false);
32396 pcm = get_per_char_metric (font, &char2b);
32397 }
32398 if (! pcm)
32399 cmp->offsets[i * 2] = cmp->offsets[i * 2 + 1] = 0;
32400 else
32401 {
32402 width = pcm->width;
32403 ascent = pcm->ascent;
32404 descent = pcm->descent;
32405 lbearing = pcm->lbearing;
32406 rbearing = pcm->rbearing;
32407 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
32408 {
32409
32410
32411 left = (leftmost + rightmost - width) / 2;
32412 btm = - descent + boff;
32413 if (font->relative_compose
32414 && (! CHAR_TABLE_P (Vignore_relative_composition)
32415 || NILP (Faref (Vignore_relative_composition,
32416 make_fixnum (ch)))))
32417 {
32418
32419 if (- descent >= font->relative_compose)
32420
32421 btm = highest + 1;
32422 else if (ascent <= 0)
32423
32424 btm = lowest - 1 - ascent - descent;
32425 }
32426 }
32427 else
32428 {
32429
32430
32431
32432
32433
32434
32435
32436
32437
32438
32439
32440
32441
32442
32443
32444 int rule = COMPOSITION_RULE (cmp, i);
32445 int gref, nref, grefx, grefy, nrefx, nrefy, xoff, yoff;
32446
32447 COMPOSITION_DECODE_RULE (rule, gref, nref, xoff, yoff);
32448 grefx = gref % 3, nrefx = nref % 3;
32449 grefy = gref / 3, nrefy = nref / 3;
32450 if (xoff)
32451 xoff = font_height * (xoff - 128) / 256;
32452 if (yoff)
32453 yoff = font_height * (yoff - 128) / 256;
32454
32455 left = (leftmost
32456 + grefx * (rightmost - leftmost) / 2
32457 - nrefx * width / 2
32458 + xoff);
32459
32460 btm = ((grefy == 0 ? highest
32461 : grefy == 1 ? 0
32462 : grefy == 2 ? lowest
32463 : (highest + lowest) / 2)
32464 - (nrefy == 0 ? ascent + descent
32465 : nrefy == 1 ? descent - boff
32466 : nrefy == 2 ? 0
32467 : (ascent + descent) / 2)
32468 + yoff);
32469 }
32470
32471 cmp->offsets[i * 2] = left;
32472 cmp->offsets[i * 2 + 1] = btm + descent;
32473
32474
32475 if (width > 0)
32476 {
32477 right = left + width;
32478 if (left < leftmost)
32479 leftmost = left;
32480 if (right > rightmost)
32481 rightmost = right;
32482 }
32483 top = btm + descent + ascent;
32484 if (top > highest)
32485 highest = top;
32486 if (btm < lowest)
32487 lowest = btm;
32488
32489 if (cmp->lbearing > left + lbearing)
32490 cmp->lbearing = left + lbearing;
32491 if (cmp->rbearing < left + rbearing)
32492 cmp->rbearing = left + rbearing;
32493 }
32494 }
32495
32496
32497
32498
32499 if (leftmost < 0)
32500 {
32501 for (i = 0; i < cmp->glyph_len; i++)
32502 cmp->offsets[i * 2] -= leftmost;
32503 rightmost -= leftmost;
32504 cmp->lbearing -= leftmost;
32505 cmp->rbearing -= leftmost;
32506 }
32507
32508 if (left_padded && cmp->lbearing < 0)
32509 {
32510 for (i = 0; i < cmp->glyph_len; i++)
32511 cmp->offsets[i * 2] -= cmp->lbearing;
32512 rightmost -= cmp->lbearing;
32513 cmp->rbearing -= cmp->lbearing;
32514 cmp->lbearing = 0;
32515 }
32516 if (right_padded && rightmost < cmp->rbearing)
32517 {
32518 rightmost = cmp->rbearing;
32519 }
32520
32521 cmp->pixel_width = rightmost;
32522 cmp->ascent = highest;
32523 cmp->descent = - lowest;
32524 if (cmp->ascent < font_ascent)
32525 cmp->ascent = font_ascent;
32526 if (cmp->descent < font_descent)
32527 cmp->descent = font_descent;
32528 }
32529
32530 if (it->glyph_row
32531 && (cmp->lbearing < 0
32532 || cmp->rbearing > cmp->pixel_width))
32533 it->glyph_row->contains_overlapping_glyphs_p = true;
32534
32535 it->pixel_width = cmp->pixel_width;
32536 it->ascent = it->phys_ascent = cmp->ascent;
32537 it->descent = it->phys_descent = cmp->descent;
32538 IT_APPLY_FACE_BOX(it, face);
32539
32540
32541
32542 if (face->overline_p)
32543 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32544
32545 take_vertical_position_into_account (it);
32546 if (it->ascent < 0)
32547 it->ascent = 0;
32548 if (it->descent < 0)
32549 it->descent = 0;
32550
32551 if (it->glyph_row && cmp->glyph_len > 0)
32552 append_composite_glyph (it);
32553 }
32554 else if (it->what == IT_COMPOSITION)
32555 {
32556
32557 struct face *face = FACE_FROM_ID (it->f, it->face_id);
32558 Lisp_Object gstring;
32559 struct font_metrics metrics;
32560
32561 it->nglyphs = 1;
32562
32563 gstring = composition_gstring_from_id (it->cmp_it.id);
32564 it->pixel_width
32565 = composition_gstring_width (gstring, it->cmp_it.from, it->cmp_it.to,
32566 &metrics);
32567 if (it->pixel_width == 0)
32568 {
32569 it->glyph_not_available_p = true;
32570 it->phys_ascent = it->ascent;
32571 it->phys_descent = it->descent;
32572 it->pixel_width = face->font->space_width;
32573 }
32574 else
32575 {
32576 if (it->glyph_row
32577 && (metrics.lbearing < 0 || metrics.rbearing > metrics.width))
32578 it->glyph_row->contains_overlapping_glyphs_p = true;
32579 it->ascent = it->phys_ascent = metrics.ascent;
32580 it->descent = it->phys_descent = metrics.descent;
32581 }
32582 IT_APPLY_FACE_BOX(it, face);
32583
32584
32585
32586 if (face->overline_p)
32587 it->ascent += clip_to_bounds (0, overline_margin, 1000000);
32588 take_vertical_position_into_account (it);
32589 if (it->ascent < 0)
32590 it->ascent = 0;
32591 if (it->descent < 0)
32592 it->descent = 0;
32593
32594 if (it->glyph_row)
32595 append_composite_glyph (it);
32596 }
32597 else if (it->what == IT_GLYPHLESS)
32598 produce_glyphless_glyph (it, false, Qnil);
32599 else if (it->what == IT_IMAGE)
32600 produce_image_glyph (it);
32601 else if (it->what == IT_STRETCH)
32602 produce_stretch_glyph (it);
32603 else if (it->what == IT_XWIDGET)
32604 produce_xwidget_glyph (it);
32605
32606 done:
32607
32608
32609 eassert (it->ascent >= 0 && it->descent >= 0);
32610 if (it->area == TEXT_AREA)
32611 it->current_x += it->pixel_width;
32612
32613 if (extra_line_spacing > 0)
32614 {
32615 it->descent += extra_line_spacing;
32616 if (extra_line_spacing > it->max_extra_line_spacing)
32617 it->max_extra_line_spacing = extra_line_spacing;
32618 }
32619
32620 it->max_ascent = max (it->max_ascent, it->ascent);
32621 it->max_descent = max (it->max_descent, it->descent);
32622 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
32623 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
32624 }
32625
32626
32627
32628
32629
32630
32631 void
32632 gui_write_glyphs (struct window *w, struct glyph_row *updated_row,
32633 struct glyph *start, enum glyph_row_area updated_area, int len)
32634 {
32635 int x, hpos, chpos = w->phys_cursor.hpos;
32636
32637 eassert (updated_row);
32638
32639
32640
32641 if (!updated_row->reversed_p && chpos < 0)
32642 chpos = 0;
32643 if (updated_row->reversed_p && chpos >= updated_row->used[TEXT_AREA])
32644 chpos = updated_row->used[TEXT_AREA] - 1;
32645
32646 block_input ();
32647
32648
32649
32650 hpos = start - updated_row->glyphs[updated_area];
32651 x = draw_glyphs (w, w->output_cursor.x,
32652 updated_row, updated_area,
32653 hpos, hpos + len,
32654 DRAW_NORMAL_TEXT, 0);
32655
32656
32657 if (updated_area == TEXT_AREA
32658 && w->phys_cursor_on_p
32659 && w->phys_cursor.vpos == w->output_cursor.vpos
32660 && chpos >= hpos
32661 && chpos < hpos + len)
32662 w->phys_cursor_on_p = false;
32663
32664 unblock_input ();
32665
32666
32667 w->output_cursor.hpos += len;
32668 w->output_cursor.x = x;
32669 }
32670
32671
32672
32673
32674
32675 void
32676 gui_insert_glyphs (struct window *w, struct glyph_row *updated_row,
32677 struct glyph *start, enum glyph_row_area updated_area, int len)
32678 {
32679 struct frame *f;
32680 int line_height, shift_by_width, shifted_region_width;
32681 struct glyph_row *row;
32682 struct glyph *glyph;
32683 int frame_x, frame_y;
32684 ptrdiff_t hpos;
32685
32686 eassert (updated_row);
32687 block_input ();
32688 f = XFRAME (WINDOW_FRAME (w));
32689
32690
32691 row = updated_row;
32692 line_height = row->height;
32693
32694
32695 shift_by_width = 0;
32696 for (glyph = start; glyph < start + len; ++glyph)
32697 shift_by_width += glyph->pixel_width;
32698
32699
32700 shifted_region_width = (window_box_width (w, updated_area)
32701 - w->output_cursor.x
32702 - shift_by_width);
32703
32704
32705 frame_x = window_box_left (w, updated_area) + w->output_cursor.x;
32706 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, w->output_cursor.y);
32707
32708 FRAME_RIF (f)->shift_glyphs_for_insert (f, frame_x, frame_y, shifted_region_width,
32709 line_height, shift_by_width);
32710
32711
32712 hpos = start - row->glyphs[updated_area];
32713 draw_glyphs (w, w->output_cursor.x, row, updated_area,
32714 hpos, hpos + len,
32715 DRAW_NORMAL_TEXT, 0);
32716
32717
32718 w->output_cursor.hpos += len;
32719 w->output_cursor.x += shift_by_width;
32720 unblock_input ();
32721 }
32722
32723
32724
32725
32726
32727
32728
32729
32730
32731
32732 void
32733 gui_clear_end_of_line (struct window *w, struct glyph_row *updated_row,
32734 enum glyph_row_area updated_area, int to_x)
32735 {
32736 struct frame *f;
32737 int max_x, min_y, max_y;
32738 int from_x, from_y, to_y;
32739 struct face *face;
32740
32741 eassert (updated_row);
32742 f = XFRAME (w->frame);
32743 face = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
32744
32745 if (updated_row->full_width_p)
32746 max_x = (WINDOW_PIXEL_WIDTH (w)
32747 - (updated_row->mode_line_p ? WINDOW_RIGHT_DIVIDER_WIDTH (w) : 0));
32748 else
32749 max_x = window_box_width (w, updated_area);
32750 max_y = window_text_bottom_y (w);
32751
32752
32753
32754 if (to_x == 0)
32755 return;
32756 else if (to_x < 0)
32757 to_x = max_x;
32758 else
32759 to_x = min (to_x, max_x);
32760
32761 to_y = min (max_y, w->output_cursor.y + updated_row->height);
32762
32763
32764 if (!updated_row->full_width_p)
32765 notice_overwritten_cursor (w, updated_area,
32766 w->output_cursor.x, -1,
32767 updated_row->y,
32768 MATRIX_ROW_BOTTOM_Y (updated_row));
32769
32770 from_x = w->output_cursor.x;
32771
32772
32773 if (updated_row->full_width_p)
32774 {
32775 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
32776 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
32777 }
32778 else
32779 {
32780 int area_left = window_box_left (w, updated_area);
32781 from_x += area_left;
32782 to_x += area_left;
32783 }
32784
32785 min_y = WINDOW_TAB_LINE_HEIGHT (w) + WINDOW_HEADER_LINE_HEIGHT (w);
32786 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, w->output_cursor.y));
32787 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
32788
32789
32790 if (to_x > from_x && to_y > from_y)
32791 {
32792 block_input ();
32793 FRAME_RIF (f)->clear_frame_area (f, from_x, from_y,
32794 to_x - from_x, to_y - from_y);
32795
32796 if (face && !updated_row->stipple_p)
32797 updated_row->stipple_p = face->stipple;
32798 unblock_input ();
32799 }
32800 }
32801
32802 #endif
32803
32804
32805
32806
32807
32808
32809
32810
32811
32812
32813
32814 static enum text_cursor_kinds
32815 get_specified_cursor_type (Lisp_Object arg, int *width)
32816 {
32817 enum text_cursor_kinds type;
32818
32819 if (NILP (arg))
32820 return NO_CURSOR;
32821
32822 if (EQ (arg, Qbox))
32823 return FILLED_BOX_CURSOR;
32824
32825 if (EQ (arg, Qhollow))
32826 return HOLLOW_BOX_CURSOR;
32827
32828 if (EQ (arg, Qbar))
32829 {
32830 *width = 2;
32831 return BAR_CURSOR;
32832 }
32833
32834 if (EQ (arg, Qhbar))
32835 {
32836 *width = 2;
32837 return HBAR_CURSOR;
32838 }
32839
32840 if (CONSP (arg)
32841 && RANGED_FIXNUMP (0, XCDR (arg), INT_MAX))
32842 {
32843 *width = XFIXNUM (XCDR (arg));
32844
32845 if (EQ (XCAR (arg), Qbox))
32846 return FILLED_BOX_CURSOR;
32847 else if (EQ (XCAR (arg), Qbar))
32848 return BAR_CURSOR;
32849 else if (EQ (XCAR (arg), Qhbar))
32850 return HBAR_CURSOR;
32851 }
32852
32853
32854
32855
32856 type = HOLLOW_BOX_CURSOR;
32857
32858 return type;
32859 }
32860
32861
32862 void
32863 set_frame_cursor_types (struct frame *f, Lisp_Object arg)
32864 {
32865 int width = 1;
32866 Lisp_Object tem;
32867
32868 FRAME_DESIRED_CURSOR (f) = get_specified_cursor_type (arg, &width);
32869 FRAME_CURSOR_WIDTH (f) = width;
32870
32871
32872
32873 tem = Fassoc (arg, Vblink_cursor_alist, Qnil);
32874 if (!NILP (tem))
32875 {
32876 FRAME_BLINK_OFF_CURSOR (f)
32877 = get_specified_cursor_type (XCDR (tem), &width);
32878 FRAME_BLINK_OFF_CURSOR_WIDTH (f) = width;
32879 }
32880 else
32881 FRAME_BLINK_OFF_CURSOR (f) = DEFAULT_CURSOR;
32882
32883
32884 f->cursor_type_changed = true;
32885 }
32886
32887
32888 #ifdef HAVE_WINDOW_SYSTEM
32889
32890
32891
32892
32893
32894
32895
32896
32897
32898
32899
32900
32901 static enum text_cursor_kinds
32902 get_window_cursor_type (struct window *w, struct glyph *glyph, int *width,
32903 bool *active_cursor)
32904 {
32905 struct frame *f = XFRAME (w->frame);
32906 struct buffer *b = XBUFFER (w->contents);
32907 int cursor_type = DEFAULT_CURSOR;
32908 Lisp_Object alt_cursor;
32909 bool non_selected = false;
32910
32911 *active_cursor = true;
32912
32913
32914 if (cursor_in_echo_area
32915 && FRAME_HAS_MINIBUF_P (f)
32916 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
32917 {
32918 if (w == XWINDOW (echo_area_window))
32919 {
32920 if (EQ (BVAR (b, cursor_type), Qt) || NILP (BVAR (b, cursor_type)))
32921 {
32922 *width = FRAME_CURSOR_WIDTH (f);
32923 return FRAME_DESIRED_CURSOR (f);
32924 }
32925 else
32926 return get_specified_cursor_type (BVAR (b, cursor_type), width);
32927 }
32928
32929 *active_cursor = false;
32930 non_selected = true;
32931 }
32932
32933
32934 else if (w != XWINDOW (f->selected_window)
32935 || f != FRAME_DISPLAY_INFO (f)->highlight_frame)
32936 {
32937 *active_cursor = false;
32938
32939 if (MINI_WINDOW_P (w) &&
32940 (minibuf_level == 0
32941 || is_minibuffer (0, w->contents)))
32942 return NO_CURSOR;
32943
32944 non_selected = true;
32945 }
32946
32947
32948 if (NILP (BVAR (b, cursor_type)))
32949 return NO_CURSOR;
32950
32951
32952 if (EQ (BVAR (b, cursor_type), Qt))
32953 {
32954 cursor_type = FRAME_DESIRED_CURSOR (f);
32955 *width = FRAME_CURSOR_WIDTH (f);
32956 }
32957 else
32958 cursor_type = get_specified_cursor_type (BVAR (b, cursor_type), width);
32959
32960
32961
32962 if (non_selected)
32963 {
32964 alt_cursor = BVAR (b, cursor_in_non_selected_windows);
32965 if (!EQ (Qt, alt_cursor))
32966 return get_specified_cursor_type (alt_cursor, width);
32967
32968 if (cursor_type == FILLED_BOX_CURSOR)
32969 cursor_type = HOLLOW_BOX_CURSOR;
32970 else if (cursor_type == BAR_CURSOR && *width > 1)
32971 --*width;
32972 return cursor_type;
32973 }
32974
32975
32976 if (!w->cursor_off_p)
32977 {
32978 if (glyph != NULL && glyph->type == XWIDGET_GLYPH)
32979 return NO_CURSOR;
32980 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
32981 {
32982 if (cursor_type == FILLED_BOX_CURSOR)
32983 {
32984
32985
32986
32987
32988 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
32989 if (img != NULL && IMAGEP (img->spec))
32990 {
32991
32992
32993
32994
32995
32996
32997 if (!img->mask
32998 || (CONSP (BVAR (b, cursor_type))
32999 && img->width > max (*width, WINDOW_FRAME_COLUMN_WIDTH (w))
33000 && img->height > max (*width, WINDOW_FRAME_LINE_HEIGHT (w))))
33001 cursor_type = HOLLOW_BOX_CURSOR;
33002 }
33003 }
33004 else if (cursor_type != NO_CURSOR)
33005 {
33006
33007
33008
33009 cursor_type = HOLLOW_BOX_CURSOR;
33010 }
33011 }
33012 return cursor_type;
33013 }
33014
33015
33016
33017
33018 if ((alt_cursor = Fassoc (BVAR (b, cursor_type), Vblink_cursor_alist, Qnil), !NILP (alt_cursor)))
33019 return get_specified_cursor_type (XCDR (alt_cursor), width);
33020
33021
33022 if (FRAME_BLINK_OFF_CURSOR (f) != DEFAULT_CURSOR)
33023 {
33024 *width = FRAME_BLINK_OFF_CURSOR_WIDTH (f);
33025 return FRAME_BLINK_OFF_CURSOR (f);
33026 }
33027
33028 #if false
33029
33030
33031
33032
33033
33034
33035
33036
33037
33038
33039 if (cursor_type == FILLED_BOX_CURSOR)
33040 return HOLLOW_BOX_CURSOR;
33041
33042 if ((cursor_type == BAR_CURSOR || cursor_type == HBAR_CURSOR) && *width > 1)
33043 {
33044 *width = 1;
33045 return cursor_type;
33046 }
33047 #endif
33048
33049 return NO_CURSOR;
33050 }
33051
33052
33053
33054
33055
33056
33057
33058
33059
33060 static void
33061 notice_overwritten_cursor (struct window *w, enum glyph_row_area area,
33062 int x0, int x1, int y0, int y1)
33063 {
33064 int cx0, cx1, cy0, cy1;
33065 struct glyph_row *row;
33066
33067 if (!w->phys_cursor_on_p)
33068 return;
33069 if (area != TEXT_AREA)
33070 return;
33071
33072 if (w->phys_cursor.vpos < 0
33073 || w->phys_cursor.vpos >= w->current_matrix->nrows
33074 || (row = w->current_matrix->rows + w->phys_cursor.vpos,
33075 !(row->enabled_p && MATRIX_ROW_DISPLAYS_TEXT_P (row))))
33076 return;
33077
33078 if (row->cursor_in_fringe_p)
33079 {
33080 row->cursor_in_fringe_p = false;
33081 draw_fringe_bitmap (w, row, row->reversed_p);
33082 w->phys_cursor_on_p = false;
33083 return;
33084 }
33085
33086 cx0 = w->phys_cursor.x;
33087 cx1 = cx0 + w->phys_cursor_width;
33088 if (x0 > cx0 || (x1 >= 0 && x1 < cx1))
33089 return;
33090
33091
33092
33093
33094
33095
33096
33097
33098
33099
33100
33101
33102
33103
33104
33105
33106
33107 cy0 = w->phys_cursor.y;
33108 cy1 = cy0 + w->phys_cursor_height;
33109 if ((y0 < cy0 || y0 >= cy1) && (y1 <= cy0 || y1 >= cy1))
33110 return;
33111
33112 w->phys_cursor_on_p = false;
33113 }
33114
33115 #endif
33116
33117
33118
33119
33120
33121
33122 #ifdef HAVE_WINDOW_SYSTEM
33123
33124
33125
33126
33127
33128 void
33129 gui_fix_overlapping_area (struct window *w, struct glyph_row *row,
33130 enum glyph_row_area area, int overlaps)
33131 {
33132 int i, x;
33133
33134 block_input ();
33135
33136 x = 0;
33137 for (i = 0; i < row->used[area];)
33138 {
33139 if (row->glyphs[area][i].overlaps_vertically_p)
33140 {
33141 int start = i, start_x = x;
33142
33143 do
33144 {
33145 x += row->glyphs[area][i].pixel_width;
33146 ++i;
33147 }
33148 while (i < row->used[area]
33149 && row->glyphs[area][i].overlaps_vertically_p);
33150
33151 draw_glyphs (w, start_x, row, area,
33152 start, i,
33153 DRAW_NORMAL_TEXT, overlaps);
33154 }
33155 else
33156 {
33157 x += row->glyphs[area][i].pixel_width;
33158 ++i;
33159 }
33160 }
33161
33162 unblock_input ();
33163 }
33164
33165
33166
33167
33168
33169
33170 void
33171 draw_phys_cursor_glyph (struct window *w, struct glyph_row *row,
33172 enum draw_glyphs_face hl)
33173 {
33174
33175
33176
33177 if ((row->reversed_p
33178 ? (w->phys_cursor.hpos >= 0)
33179 : (w->phys_cursor.hpos < row->used[TEXT_AREA])))
33180 {
33181 bool on_p = w->phys_cursor_on_p;
33182 int x1;
33183 int hpos = w->phys_cursor.hpos;
33184
33185
33186
33187
33188 if (!row->reversed_p && hpos < 0)
33189 hpos = 0;
33190 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33191 hpos = row->used[TEXT_AREA] - 1;
33192
33193 x1 = draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA, hpos, hpos + 1,
33194 hl, 0);
33195 w->phys_cursor_on_p = on_p;
33196
33197 if (hl == DRAW_CURSOR)
33198 w->phys_cursor_width = x1 - w->phys_cursor.x;
33199
33200
33201
33202 else if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
33203 {
33204 w->phys_cursor_width = x1 - w->phys_cursor.x;
33205
33206 if (row > w->current_matrix->rows
33207 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
33208 gui_fix_overlapping_area (w, row - 1, TEXT_AREA,
33209 OVERLAPS_ERASED_CURSOR);
33210
33211 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
33212 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
33213 gui_fix_overlapping_area (w, row + 1, TEXT_AREA,
33214 OVERLAPS_ERASED_CURSOR);
33215 }
33216 }
33217 }
33218
33219
33220
33221
33222 void
33223 erase_phys_cursor (struct window *w)
33224 {
33225 struct frame *f = XFRAME (w->frame);
33226 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
33227 int hpos = w->phys_cursor.hpos;
33228 int vpos = w->phys_cursor.vpos;
33229 bool mouse_face_here_p = false;
33230 struct glyph_matrix *active_glyphs = w->current_matrix;
33231 struct glyph_row *cursor_row;
33232 struct glyph *cursor_glyph;
33233 enum draw_glyphs_face hl;
33234
33235
33236
33237 if (w->phys_cursor_type == NO_CURSOR)
33238 goto mark_cursor_off;
33239
33240
33241
33242 if (vpos >= active_glyphs->nrows)
33243 goto mark_cursor_off;
33244
33245
33246
33247 cursor_row = MATRIX_ROW (active_glyphs, vpos);
33248 if (!cursor_row->enabled_p)
33249 goto mark_cursor_off;
33250
33251
33252
33253 cursor_row->visible_height = min (cursor_row->visible_height,
33254 window_text_bottom_y (w) - cursor_row->y);
33255
33256
33257
33258
33259 if (cursor_row->visible_height <= 0)
33260 goto mark_cursor_off;
33261
33262
33263 if (cursor_row->cursor_in_fringe_p)
33264 {
33265 cursor_row->cursor_in_fringe_p = false;
33266 draw_fringe_bitmap (w, cursor_row, cursor_row->reversed_p);
33267 goto mark_cursor_off;
33268 }
33269
33270
33271
33272
33273
33274
33275 if ((cursor_row->reversed_p
33276 ? (w->phys_cursor.hpos < 0)
33277 : (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])))
33278 goto mark_cursor_off;
33279
33280
33281
33282
33283 if (!cursor_row->reversed_p && hpos < 0)
33284 hpos = 0;
33285 if (cursor_row->reversed_p && hpos >= cursor_row->used[TEXT_AREA])
33286 hpos = cursor_row->used[TEXT_AREA] - 1;
33287
33288
33289
33290 if (! NILP (hlinfo->mouse_face_window)
33291 && coords_in_mouse_face_p (w, hpos, vpos)
33292
33293
33294
33295 && cursor_row->used[TEXT_AREA] > hpos && hpos >= 0)
33296 mouse_face_here_p = true;
33297
33298 #ifdef HAVE_WINDOW_SYSTEM
33299
33300
33301
33302
33303 if (FRAME_WINDOW_P (WINDOW_XFRAME (w)) && mouse_face_here_p)
33304 {
33305 w->phys_cursor_on_p = false;
33306 w->phys_cursor_type = NO_CURSOR;
33307 show_mouse_face (MOUSE_HL_INFO (WINDOW_XFRAME (w)), DRAW_MOUSE_FACE);
33308 return;
33309 }
33310 #endif
33311
33312
33313 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
33314 {
33315 int x, y;
33316 int tab_line_height = WINDOW_TAB_LINE_HEIGHT (w);
33317 int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w);
33318 int width;
33319
33320 cursor_glyph = get_phys_cursor_glyph (w);
33321 if (cursor_glyph == NULL)
33322 goto mark_cursor_off;
33323
33324 width = cursor_glyph->pixel_width;
33325 x = w->phys_cursor.x;
33326 if (x < 0)
33327 {
33328 width += x;
33329 x = 0;
33330 }
33331 width = min (width, window_box_width (w, TEXT_AREA) - x);
33332 y = WINDOW_TO_FRAME_PIXEL_Y (w, max (tab_line_height, max (header_line_height, cursor_row->y)));
33333 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, x);
33334
33335 if (width > 0)
33336 FRAME_RIF (f)->clear_frame_area (f, x, y, width, cursor_row->visible_height);
33337 }
33338
33339
33340 if (mouse_face_here_p)
33341 hl = DRAW_MOUSE_FACE;
33342 else
33343 hl = DRAW_NORMAL_TEXT;
33344 draw_phys_cursor_glyph (w, cursor_row, hl);
33345
33346 mark_cursor_off:
33347 w->phys_cursor_on_p = false;
33348 w->phys_cursor_type = NO_CURSOR;
33349 }
33350
33351
33352
33353
33354
33355
33356 void
33357 display_and_set_cursor (struct window *w, bool on,
33358 int hpos, int vpos, int x, int y)
33359 {
33360 struct frame *f = XFRAME (w->frame);
33361 int new_cursor_type;
33362 int new_cursor_width UNINIT;
33363 bool active_cursor;
33364 struct glyph_row *glyph_row;
33365 struct glyph *glyph;
33366
33367
33368
33369
33370
33371 if (! FRAME_VISIBLE_P (f)
33372 || vpos >= w->current_matrix->nrows
33373 || hpos >= w->current_matrix->matrix_w)
33374 return;
33375
33376
33377 if (!on && !w->phys_cursor_on_p)
33378 return;
33379
33380 glyph_row = MATRIX_ROW (w->current_matrix, vpos);
33381
33382
33383 if (!glyph_row->enabled_p)
33384 {
33385 w->phys_cursor_on_p = false;
33386 return;
33387 }
33388
33389
33390
33391
33392
33393
33394
33395
33396
33397 if (FRAME_GARBAGED_P (f))
33398 {
33399 if (on)
33400 {
33401 w->phys_cursor.x = x;
33402 w->phys_cursor.y = glyph_row->y;
33403 w->phys_cursor.hpos = hpos;
33404 w->phys_cursor.vpos = vpos;
33405 }
33406 return;
33407 }
33408
33409 glyph = NULL;
33410 if (0 <= hpos && hpos < glyph_row->used[TEXT_AREA])
33411 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
33412
33413 eassert (input_blocked_p ());
33414
33415
33416 new_cursor_type = get_window_cursor_type (w, glyph,
33417 &new_cursor_width, &active_cursor);
33418
33419
33420
33421
33422 if (w->phys_cursor_on_p
33423 && (!on
33424 || w->phys_cursor.x != x
33425 || w->phys_cursor.y != y
33426
33427
33428
33429 || hpos < 0
33430 || new_cursor_type != w->phys_cursor_type
33431 || ((new_cursor_type == BAR_CURSOR || new_cursor_type == HBAR_CURSOR)
33432 && new_cursor_width != w->phys_cursor_width)))
33433 erase_phys_cursor (w);
33434
33435
33436
33437
33438
33439
33440 if (on)
33441 {
33442 w->phys_cursor_ascent = glyph_row->ascent;
33443 w->phys_cursor_height = glyph_row->height;
33444
33445
33446
33447 w->phys_cursor.x = x;
33448 w->phys_cursor.y = glyph_row->y;
33449 w->phys_cursor.hpos = hpos;
33450 w->phys_cursor.vpos = vpos;
33451 }
33452
33453 FRAME_RIF (f)->draw_window_cursor (w, glyph_row, x, y,
33454 new_cursor_type, new_cursor_width,
33455 on, active_cursor);
33456 }
33457
33458
33459
33460
33461
33462 static void
33463 update_window_cursor (struct window *w, bool on)
33464 {
33465
33466
33467 if (w->current_matrix)
33468 {
33469 int hpos = w->phys_cursor.hpos;
33470 int vpos = w->phys_cursor.vpos;
33471 struct glyph_row *row;
33472
33473 if (vpos >= w->current_matrix->nrows
33474 || hpos >= w->current_matrix->matrix_w)
33475 return;
33476
33477 row = MATRIX_ROW (w->current_matrix, vpos);
33478
33479
33480
33481
33482 if (!row->reversed_p && hpos < 0)
33483 hpos = 0;
33484 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33485 hpos = row->used[TEXT_AREA] - 1;
33486
33487 block_input ();
33488 display_and_set_cursor (w, on, hpos, vpos,
33489 w->phys_cursor.x, w->phys_cursor.y);
33490 unblock_input ();
33491 }
33492 }
33493
33494
33495
33496
33497
33498 static void
33499 update_cursor_in_window_tree (struct window *w, bool on_p)
33500 {
33501 while (w)
33502 {
33503 if (WINDOWP (w->contents))
33504 update_cursor_in_window_tree (XWINDOW (w->contents), on_p);
33505 else
33506 update_window_cursor (w, on_p);
33507
33508 w = NILP (w->next) ? 0 : XWINDOW (w->next);
33509 }
33510 }
33511
33512
33513
33514
33515
33516
33517 void
33518 gui_update_cursor (struct frame *f, bool on_p)
33519 {
33520 update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
33521 }
33522
33523
33524
33525
33526
33527
33528
33529 void
33530 gui_clear_cursor (struct window *w)
33531 {
33532 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
33533 update_window_cursor (w, false);
33534 }
33535
33536 #endif
33537
33538
33539
33540 static void
33541 draw_row_with_mouse_face (struct window *w, int start_x, struct glyph_row *row,
33542 int start_hpos, int end_hpos,
33543 enum draw_glyphs_face draw)
33544 {
33545 #ifdef HAVE_WINDOW_SYSTEM
33546 if (FRAME_WINDOW_P (XFRAME (w->frame)))
33547 {
33548 draw_glyphs (w, start_x, row, TEXT_AREA, start_hpos, end_hpos, draw, 0);
33549 return;
33550 }
33551 #endif
33552
33553 tty_draw_row_with_mouse_face (w, row, start_hpos, end_hpos, draw);
33554 }
33555
33556
33557
33558 static void
33559 show_mouse_face (Mouse_HLInfo *hlinfo, enum draw_glyphs_face draw)
33560 {
33561
33562
33563 if (!WINDOWP (hlinfo->mouse_face_window))
33564 return;
33565
33566 struct window *w = XWINDOW (hlinfo->mouse_face_window);
33567 struct frame *f = XFRAME (WINDOW_FRAME (w));
33568
33569
33570 if (f != hlinfo->mouse_face_mouse_frame)
33571 return;
33572
33573 if (
33574
33575 w->current_matrix != NULL
33576
33577 && (draw != DRAW_MOUSE_FACE || !hlinfo->mouse_face_hidden)
33578
33579
33580 && hlinfo->mouse_face_end_row < w->current_matrix->nrows)
33581 {
33582 bool phys_cursor_on_p = w->phys_cursor_on_p;
33583 #ifdef HAVE_WINDOW_SYSTEM
33584 int mouse_off = 0;
33585 #endif
33586 struct glyph_row *row, *first, *last;
33587
33588 first = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_beg_row);
33589 last = MATRIX_ROW (w->current_matrix, hlinfo->mouse_face_end_row);
33590
33591 for (row = first; row <= last && row->enabled_p; ++row)
33592 {
33593 int start_hpos, end_hpos, start_x;
33594
33595
33596 if (row == first)
33597 {
33598
33599
33600
33601
33602 if (!row->reversed_p)
33603 {
33604 start_hpos = hlinfo->mouse_face_beg_col;
33605 start_x = hlinfo->mouse_face_beg_x;
33606 }
33607 else if (row == last)
33608 {
33609 start_hpos = hlinfo->mouse_face_end_col;
33610 start_x = hlinfo->mouse_face_end_x;
33611 }
33612 else
33613 {
33614 start_hpos = 0;
33615 start_x = 0;
33616 }
33617 }
33618 else if (row->reversed_p && row == last)
33619 {
33620 start_hpos = hlinfo->mouse_face_end_col;
33621 start_x = hlinfo->mouse_face_end_x;
33622 }
33623 else
33624 {
33625 start_hpos = 0;
33626 start_x = 0;
33627 }
33628
33629 if (row == last)
33630 {
33631 if (!row->reversed_p)
33632 end_hpos = hlinfo->mouse_face_end_col;
33633 else if (row == first)
33634 end_hpos = hlinfo->mouse_face_beg_col;
33635 else
33636 {
33637 end_hpos = row->used[TEXT_AREA];
33638 if (draw == DRAW_NORMAL_TEXT)
33639 row->fill_line_p = true;
33640 }
33641 }
33642 else if (row->reversed_p && row == first)
33643 end_hpos = hlinfo->mouse_face_beg_col;
33644 else
33645 {
33646 end_hpos = row->used[TEXT_AREA];
33647 if (draw == DRAW_NORMAL_TEXT)
33648 row->fill_line_p = true;
33649 }
33650
33651 if (end_hpos > start_hpos)
33652 {
33653 draw_row_with_mouse_face (w, start_x, row,
33654 start_hpos, end_hpos, draw);
33655
33656 row->mouse_face_p
33657 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
33658 }
33659 #ifdef HAVE_WINDOW_SYSTEM
33660
33661 if ((MATRIX_ROW_VPOS (row, w->current_matrix) == w->phys_cursor.vpos)
33662
33663
33664 && !w->pseudo_window_p
33665 && draw == DRAW_MOUSE_FACE)
33666 get_cursor_offset_for_mouse_face (w, row, &mouse_off);
33667 #endif
33668 }
33669
33670
33671
33672 if (FRAME_WINDOW_P (f)
33673 && phys_cursor_on_p && !w->phys_cursor_on_p)
33674 {
33675 #ifdef HAVE_WINDOW_SYSTEM
33676 int hpos = w->phys_cursor.hpos;
33677 int old_phys_cursor_x = w->phys_cursor.x;
33678
33679
33680
33681
33682 if (!row->reversed_p && hpos < 0)
33683 hpos = 0;
33684 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33685 hpos = row->used[TEXT_AREA] - 1;
33686
33687 block_input ();
33688 display_and_set_cursor (w, true, hpos, w->phys_cursor.vpos,
33689 w->phys_cursor.x + mouse_off,
33690 w->phys_cursor.y);
33691
33692
33693 w->phys_cursor.x = old_phys_cursor_x;
33694 unblock_input ();
33695 #endif
33696 }
33697 }
33698
33699 #ifdef HAVE_WINDOW_SYSTEM
33700
33701 if (FRAME_WINDOW_P (f) && NILP (track_mouse))
33702 {
33703 if (draw == DRAW_NORMAL_TEXT
33704 #ifndef HAVE_EXT_TOOL_BAR
33705 && !EQ (hlinfo->mouse_face_window, f->tool_bar_window)
33706 #endif
33707 && !EQ (hlinfo->mouse_face_window, f->tab_bar_window))
33708 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->text_cursor);
33709 else
33710 if (draw == DRAW_MOUSE_FACE)
33711 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->hand_cursor);
33712 else
33713 FRAME_RIF (f)->define_frame_cursor (f, FRAME_OUTPUT_DATA (f)->nontext_cursor);
33714 }
33715 #endif
33716 }
33717
33718
33719
33720
33721
33722
33723 bool
33724 clear_mouse_face (Mouse_HLInfo *hlinfo)
33725 {
33726 bool cleared
33727 = !hlinfo->mouse_face_hidden && !NILP (hlinfo->mouse_face_window);
33728 if (cleared)
33729 show_mouse_face (hlinfo, DRAW_NORMAL_TEXT);
33730 hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
33731 hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
33732 hlinfo->mouse_face_window = Qnil;
33733 hlinfo->mouse_face_overlay = Qnil;
33734 return cleared;
33735 }
33736
33737
33738
33739 static bool
33740 coords_in_mouse_face_p (struct window *w, int hpos, int vpos)
33741 {
33742 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
33743
33744
33745 if (!(WINDOWP (hlinfo->mouse_face_window)
33746 && XWINDOW (hlinfo->mouse_face_window) == w))
33747 return false;
33748 if (vpos < hlinfo->mouse_face_beg_row
33749 || vpos > hlinfo->mouse_face_end_row)
33750 return false;
33751 if (vpos > hlinfo->mouse_face_beg_row
33752 && vpos < hlinfo->mouse_face_end_row)
33753 return true;
33754
33755 if (!MATRIX_ROW (w->current_matrix, vpos)->reversed_p)
33756 {
33757 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
33758 {
33759 if (hlinfo->mouse_face_beg_col <= hpos && hpos < hlinfo->mouse_face_end_col)
33760 return true;
33761 }
33762 else if ((vpos == hlinfo->mouse_face_beg_row
33763 && hpos >= hlinfo->mouse_face_beg_col)
33764 || (vpos == hlinfo->mouse_face_end_row
33765 && hpos < hlinfo->mouse_face_end_col))
33766 return true;
33767 }
33768 else
33769 {
33770 if (hlinfo->mouse_face_beg_row == hlinfo->mouse_face_end_row)
33771 {
33772 if (hlinfo->mouse_face_end_col < hpos && hpos <= hlinfo->mouse_face_beg_col)
33773 return true;
33774 }
33775 else if ((vpos == hlinfo->mouse_face_beg_row
33776 && hpos <= hlinfo->mouse_face_beg_col)
33777 || (vpos == hlinfo->mouse_face_end_row
33778 && hpos > hlinfo->mouse_face_end_col))
33779 return true;
33780 }
33781 return false;
33782 }
33783
33784
33785
33786
33787
33788 bool
33789 cursor_in_mouse_face_p (struct window *w)
33790 {
33791 int vpos = w->phys_cursor.vpos;
33792
33793
33794
33795 if (!(0 <= vpos && vpos < w->current_matrix->nrows))
33796 return false;
33797
33798 int hpos = w->phys_cursor.hpos;
33799 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
33800
33801
33802
33803
33804 if (!row->reversed_p && hpos < 0)
33805 hpos = 0;
33806 if (row->reversed_p && hpos >= row->used[TEXT_AREA])
33807 hpos = row->used[TEXT_AREA] - 1;
33808
33809 return coords_in_mouse_face_p (w, hpos, vpos);
33810 }
33811
33812
33813
33814
33815
33816
33817
33818
33819
33820 static void
33821 rows_from_pos_range (struct window *w,
33822 ptrdiff_t start_charpos, ptrdiff_t end_charpos,
33823 Lisp_Object disp_string,
33824 struct glyph_row **start, struct glyph_row **end)
33825 {
33826 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
33827 int last_y = window_text_bottom_y (w);
33828 struct glyph_row *row;
33829
33830 *start = NULL;
33831 *end = NULL;
33832
33833 while (!first->enabled_p
33834 && first < MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w))
33835 first++;
33836
33837
33838 for (row = first;
33839 row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y;
33840 row++)
33841 {
33842
33843
33844
33845 if (! ((start_charpos < MATRIX_ROW_START_CHARPOS (row)
33846 && end_charpos < MATRIX_ROW_START_CHARPOS (row))
33847
33848
33849
33850
33851 || ((start_charpos > MATRIX_ROW_END_CHARPOS (row)
33852 || (start_charpos == MATRIX_ROW_END_CHARPOS (row)
33853 && !row->ends_at_zv_p
33854 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row)))
33855 && (end_charpos > MATRIX_ROW_END_CHARPOS (row)
33856 || (end_charpos == MATRIX_ROW_END_CHARPOS (row)
33857 && !row->ends_at_zv_p
33858 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (row))))))
33859 {
33860
33861
33862
33863
33864
33865
33866
33867
33868
33869
33870 struct glyph *g = row->glyphs[TEXT_AREA];
33871 struct glyph *e = g + row->used[TEXT_AREA];
33872
33873 while (g < e)
33874 {
33875 if (((BUFFERP (g->object) || NILP (g->object))
33876 && start_charpos <= g->charpos && g->charpos < end_charpos)
33877
33878
33879 || EQ (g->object, disp_string))
33880 *start = row;
33881 g++;
33882 }
33883 if (*start)
33884 break;
33885 }
33886 }
33887
33888
33889 if (!*start
33890
33891
33892 && !(row->enabled_p
33893 && row->y < last_y && MATRIX_ROW_BOTTOM_Y (row) > last_y))
33894 row = first;
33895 for ( ; row->enabled_p && MATRIX_ROW_BOTTOM_Y (row) <= last_y; row++)
33896 {
33897 struct glyph_row *next = row + 1;
33898 ptrdiff_t next_start = MATRIX_ROW_START_CHARPOS (next);
33899
33900 if (!next->enabled_p
33901 || next >= MATRIX_BOTTOM_TEXT_ROW (w->current_matrix, w)
33902
33903
33904
33905 || (start_charpos < next_start
33906 && end_charpos < next_start)
33907 || ((start_charpos > MATRIX_ROW_END_CHARPOS (next)
33908 || (start_charpos == MATRIX_ROW_END_CHARPOS (next)
33909 && !next->ends_at_zv_p
33910 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))
33911 && (end_charpos > MATRIX_ROW_END_CHARPOS (next)
33912 || (end_charpos == MATRIX_ROW_END_CHARPOS (next)
33913 && !next->ends_at_zv_p
33914 && !MATRIX_ROW_ENDS_IN_MIDDLE_OF_CHAR_P (next)))))
33915 {
33916 *end = row;
33917 break;
33918 }
33919 else
33920 {
33921
33922
33923
33924 struct glyph *g = next->glyphs[TEXT_AREA];
33925 struct glyph *s = g;
33926 struct glyph *e = g + next->used[TEXT_AREA];
33927
33928 while (g < e)
33929 {
33930 if (((BUFFERP (g->object) || NILP (g->object))
33931 && ((start_charpos <= g->charpos && g->charpos < end_charpos)
33932
33933
33934
33935
33936
33937 || (((!next->reversed_p && g == s)
33938 || (next->reversed_p && g == e - 1))
33939 && (g->charpos == end_charpos
33940
33941
33942 || (g->charpos == -1
33943 && !row->ends_at_zv_p
33944 && next_start == end_charpos)))))
33945
33946
33947 || EQ (g->object, disp_string))
33948 break;
33949 g++;
33950 }
33951 if (g == e)
33952 {
33953 *end = row;
33954 break;
33955 }
33956
33957
33958 else if (next->ends_at_zv_p)
33959 {
33960 *end = next;
33961 break;
33962 }
33963 }
33964 }
33965 }
33966
33967
33968
33969
33970
33971
33972
33973
33974
33975
33976 static void
33977 mouse_face_from_buffer_pos (Lisp_Object window,
33978 Mouse_HLInfo *hlinfo,
33979 ptrdiff_t mouse_charpos,
33980 ptrdiff_t start_charpos,
33981 ptrdiff_t end_charpos,
33982 Lisp_Object before_string,
33983 Lisp_Object after_string,
33984 Lisp_Object disp_string)
33985 {
33986 struct window *w = XWINDOW (window);
33987 struct glyph_row *first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
33988 struct glyph_row *r1, *r2;
33989 struct glyph *glyph, *end;
33990 ptrdiff_t ignore, pos;
33991 int x;
33992
33993 eassert (NILP (disp_string) || STRINGP (disp_string));
33994 eassert (NILP (before_string) || STRINGP (before_string));
33995 eassert (NILP (after_string) || STRINGP (after_string));
33996
33997
33998 rows_from_pos_range (w, start_charpos, end_charpos, disp_string, &r1, &r2);
33999 if (r1 == NULL)
34000 r1 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34001
34002
34003 if (!NILP (before_string) || !NILP (disp_string))
34004 {
34005 struct glyph_row *prev;
34006 while ((prev = r1 - 1, prev >= first)
34007 && MATRIX_ROW_END_CHARPOS (prev) == start_charpos
34008 && prev->used[TEXT_AREA] > 0)
34009 {
34010 struct glyph *beg = prev->glyphs[TEXT_AREA];
34011 glyph = beg + prev->used[TEXT_AREA];
34012 while (--glyph >= beg && NILP (glyph->object));
34013 if (glyph < beg
34014 || !(EQ (glyph->object, before_string)
34015 || EQ (glyph->object, disp_string)))
34016 break;
34017 r1 = prev;
34018 }
34019 }
34020 if (r2 == NULL)
34021 {
34022 r2 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34023 hlinfo->mouse_face_past_end = true;
34024 }
34025 else if (!NILP (after_string))
34026 {
34027
34028 struct glyph_row *next;
34029 struct glyph_row *last
34030 = MATRIX_ROW (w->current_matrix, w->window_end_vpos);
34031
34032 for (next = r2 + 1;
34033 next <= last
34034 && next->used[TEXT_AREA] > 0
34035 && EQ (next->glyphs[TEXT_AREA]->object, after_string);
34036 ++next)
34037 r2 = next;
34038 }
34039
34040
34041
34042
34043
34044 if (r1->y > r2->y)
34045 {
34046 struct glyph_row *tem = r2;
34047
34048 r2 = r1;
34049 r1 = tem;
34050 }
34051
34052 hlinfo->mouse_face_beg_row = MATRIX_ROW_VPOS (r1, w->current_matrix);
34053 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r2, w->current_matrix);
34054
34055
34056
34057
34058
34059
34060
34061
34062
34063
34064
34065 if (!r1->reversed_p)
34066 {
34067
34068
34069 glyph = r1->glyphs[TEXT_AREA];
34070 end = glyph + r1->used[TEXT_AREA];
34071 x = r1->x;
34072
34073
34074 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34075 for (; glyph < end
34076 && NILP (glyph->object)
34077 && glyph->charpos < 0;
34078 ++glyph)
34079 x += glyph->pixel_width;
34080
34081
34082
34083
34084 for (; glyph < end
34085 && !NILP (glyph->object)
34086 && !EQ (glyph->object, disp_string)
34087 && !(BUFFERP (glyph->object)
34088 && (glyph->charpos >= start_charpos
34089 && glyph->charpos < end_charpos));
34090 ++glyph)
34091 {
34092
34093
34094
34095 if (EQ (glyph->object, before_string))
34096 {
34097 pos = string_buffer_position (before_string,
34098 start_charpos);
34099
34100
34101 if (!pos || (pos >= start_charpos && pos < end_charpos))
34102 break;
34103 }
34104 else if (EQ (glyph->object, after_string))
34105 {
34106 pos = string_buffer_position (after_string, end_charpos);
34107 if (!pos || (pos >= start_charpos && pos < end_charpos))
34108 break;
34109 }
34110 x += glyph->pixel_width;
34111 }
34112 hlinfo->mouse_face_beg_x = x;
34113 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34114 }
34115 else
34116 {
34117
34118
34119 struct glyph *g;
34120
34121 end = r1->glyphs[TEXT_AREA] - 1;
34122 glyph = end + r1->used[TEXT_AREA];
34123
34124
34125 if (MATRIX_ROW_DISPLAYS_TEXT_P (r1))
34126 for (; glyph > end
34127 && NILP (glyph->object)
34128 && glyph->charpos < 0;
34129 --glyph)
34130 ;
34131
34132
34133
34134
34135 for (; glyph > end
34136 && !NILP (glyph->object)
34137 && !EQ (glyph->object, disp_string)
34138 && !(BUFFERP (glyph->object)
34139 && (glyph->charpos >= start_charpos
34140 && glyph->charpos < end_charpos));
34141 --glyph)
34142 {
34143
34144
34145
34146 if (EQ (glyph->object, before_string))
34147 {
34148 pos = string_buffer_position (before_string, start_charpos);
34149
34150
34151 if (!pos || (pos >= start_charpos && pos < end_charpos))
34152 break;
34153 }
34154 else if (EQ (glyph->object, after_string))
34155 {
34156 pos = string_buffer_position (after_string, end_charpos);
34157 if (!pos || (pos >= start_charpos && pos < end_charpos))
34158 break;
34159 }
34160 }
34161
34162 glyph++;
34163 for (g = r1->glyphs[TEXT_AREA], x = r1->x; g < glyph; g++)
34164 x += g->pixel_width;
34165 hlinfo->mouse_face_beg_x = x;
34166 hlinfo->mouse_face_beg_col = glyph - r1->glyphs[TEXT_AREA];
34167 }
34168
34169
34170
34171
34172 if (r2 != r1)
34173 {
34174 if (!r2->reversed_p)
34175 {
34176 glyph = r2->glyphs[TEXT_AREA];
34177 end = glyph + r2->used[TEXT_AREA];
34178 x = r2->x;
34179 }
34180 else
34181 {
34182 end = r2->glyphs[TEXT_AREA] - 1;
34183 glyph = end + r2->used[TEXT_AREA];
34184 }
34185 }
34186
34187 if (!r2->reversed_p)
34188 {
34189
34190
34191
34192 while (end > glyph
34193 && NILP ((end - 1)->object))
34194 --end;
34195
34196
34197
34198
34199 for (--end;
34200 end > glyph
34201 && !NILP (end->object)
34202 && !EQ (end->object, disp_string)
34203 && !(BUFFERP (end->object)
34204 && (end->charpos >= start_charpos
34205 && end->charpos < end_charpos));
34206 --end)
34207 {
34208
34209
34210
34211 if (EQ (end->object, before_string))
34212 {
34213 pos = string_buffer_position (before_string, start_charpos);
34214 if (!pos || (pos >= start_charpos && pos < end_charpos))
34215 break;
34216 }
34217 else if (EQ (end->object, after_string))
34218 {
34219 pos = string_buffer_position (after_string, end_charpos);
34220 if (!pos || (pos >= start_charpos && pos < end_charpos))
34221 break;
34222 }
34223 }
34224
34225 for (; glyph <= end; ++glyph)
34226 x += glyph->pixel_width;
34227
34228 hlinfo->mouse_face_end_x = x;
34229 hlinfo->mouse_face_end_col = glyph - r2->glyphs[TEXT_AREA];
34230 }
34231 else
34232 {
34233
34234
34235
34236 x = r2->x;
34237 end++;
34238 while (end < glyph
34239 && NILP (end->object))
34240 {
34241 x += end->pixel_width;
34242 ++end;
34243 }
34244
34245
34246
34247
34248 for ( ;
34249 end < glyph
34250 && !NILP (end->object)
34251 && !EQ (end->object, disp_string)
34252 && !(BUFFERP (end->object)
34253 && (end->charpos >= start_charpos
34254 && end->charpos < end_charpos));
34255 ++end)
34256 {
34257
34258
34259
34260 if (EQ (end->object, before_string))
34261 {
34262 pos = string_buffer_position (before_string, start_charpos);
34263 if (!pos || (pos >= start_charpos && pos < end_charpos))
34264 break;
34265 }
34266 else if (EQ (end->object, after_string))
34267 {
34268 pos = string_buffer_position (after_string, end_charpos);
34269 if (!pos || (pos >= start_charpos && pos < end_charpos))
34270 break;
34271 }
34272 x += end->pixel_width;
34273 }
34274
34275
34276
34277
34278
34279 if (end == glyph
34280 && BUFFERP (end->object)
34281 && (end->charpos < start_charpos
34282 || end->charpos >= end_charpos))
34283 {
34284 x += end->pixel_width;
34285 ++end;
34286 }
34287 hlinfo->mouse_face_end_x = x;
34288 hlinfo->mouse_face_end_col = end - r2->glyphs[TEXT_AREA];
34289 }
34290
34291 hlinfo->mouse_face_window = window;
34292 hlinfo->mouse_face_face_id
34293 = face_at_buffer_position (w, mouse_charpos, &ignore,
34294 mouse_charpos + 1,
34295 !hlinfo->mouse_face_hidden, -1, 0);
34296 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
34297 }
34298
34299
34300
34301
34302
34303 #if false
34304
34305
34306
34307
34308
34309
34310
34311
34312
34313
34314
34315
34316
34317
34318
34319
34320 static bool
34321 fast_find_string_pos (struct window *w, ptrdiff_t pos, Lisp_Object object,
34322 int *hpos, int *vpos, int *x, int *y, bool right_p)
34323 {
34324 int yb = window_text_bottom_y (w);
34325 struct glyph_row *r;
34326 struct glyph *best_glyph = NULL;
34327 struct glyph_row *best_row = NULL;
34328 int best_x = 0;
34329
34330 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34331 r->enabled_p && r->y < yb;
34332 ++r)
34333 {
34334 struct glyph *g = r->glyphs[TEXT_AREA];
34335 struct glyph *e = g + r->used[TEXT_AREA];
34336 int gx;
34337
34338 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34339 if (EQ (g->object, object))
34340 {
34341 if (g->charpos == pos)
34342 {
34343 best_glyph = g;
34344 best_x = gx;
34345 best_row = r;
34346 goto found;
34347 }
34348 else if (best_glyph == NULL
34349 || ((eabs (g->charpos - pos)
34350 < eabs (best_glyph->charpos - pos))
34351 && (right_p
34352 ? g->charpos < pos
34353 : g->charpos > pos)))
34354 {
34355 best_glyph = g;
34356 best_x = gx;
34357 best_row = r;
34358 }
34359 }
34360 }
34361
34362 found:
34363
34364 if (best_glyph)
34365 {
34366 *x = best_x;
34367 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
34368
34369 if (right_p)
34370 {
34371 *x += best_glyph->pixel_width;
34372 ++*hpos;
34373 }
34374
34375 *y = best_row->y;
34376 *vpos = MATRIX_ROW_VPOS (best_row, w->current_matrix);
34377 }
34378
34379 return best_glyph != NULL;
34380 }
34381 #endif
34382
34383
34384
34385
34386
34387
34388 static void
34389 mouse_face_from_string_pos (struct window *w, Mouse_HLInfo *hlinfo,
34390 Lisp_Object object,
34391 ptrdiff_t startpos, ptrdiff_t endpos)
34392 {
34393 int yb = window_text_bottom_y (w);
34394 struct glyph_row *r;
34395 struct glyph *g, *e;
34396 int gx;
34397 bool found = false;
34398
34399
34400
34401
34402 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
34403 r->enabled_p && r->y < yb;
34404 ++r)
34405 {
34406 if (!r->reversed_p)
34407 {
34408 g = r->glyphs[TEXT_AREA];
34409 e = g + r->used[TEXT_AREA];
34410 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
34411 if (EQ (g->object, object)
34412 && startpos <= g->charpos && g->charpos < endpos)
34413 {
34414 hlinfo->mouse_face_beg_row
34415 = MATRIX_ROW_VPOS (r, w->current_matrix);
34416 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34417 hlinfo->mouse_face_beg_x = gx;
34418 found = true;
34419 break;
34420 }
34421 }
34422 else
34423 {
34424 struct glyph *g1;
34425
34426 e = r->glyphs[TEXT_AREA];
34427 g = e + r->used[TEXT_AREA];
34428 for ( ; g > e; --g)
34429 if (EQ ((g-1)->object, object)
34430 && startpos <= (g-1)->charpos && (g-1)->charpos < endpos)
34431 {
34432 hlinfo->mouse_face_beg_row
34433 = MATRIX_ROW_VPOS (r, w->current_matrix);
34434 hlinfo->mouse_face_beg_col = g - r->glyphs[TEXT_AREA];
34435 for (gx = r->x, g1 = r->glyphs[TEXT_AREA]; g1 < g; ++g1)
34436 gx += g1->pixel_width;
34437 hlinfo->mouse_face_beg_x = gx;
34438 found = true;
34439 break;
34440 }
34441 }
34442 if (found)
34443 break;
34444 }
34445
34446 if (!found)
34447 return;
34448
34449
34450
34451 for (++r; r->enabled_p && r->y < yb; ++r)
34452 {
34453 g = r->glyphs[TEXT_AREA];
34454 e = g + r->used[TEXT_AREA];
34455 found = false;
34456 for ( ; g < e; ++g)
34457 if (EQ (g->object, object)
34458 && startpos <= g->charpos && g->charpos < endpos)
34459 {
34460 found = true;
34461 break;
34462 }
34463 if (!found)
34464 break;
34465 }
34466
34467
34468 r--;
34469
34470
34471 hlinfo->mouse_face_end_row = MATRIX_ROW_VPOS (r, w->current_matrix);
34472
34473
34474
34475 if (!r->reversed_p)
34476 {
34477 g = r->glyphs[TEXT_AREA];
34478 e = g + r->used[TEXT_AREA];
34479 for ( ; e > g; --e)
34480 if (EQ ((e-1)->object, object)
34481 && startpos <= (e-1)->charpos && (e-1)->charpos < endpos)
34482 break;
34483 hlinfo->mouse_face_end_col = e - g;
34484
34485 for (gx = r->x; g < e; ++g)
34486 gx += g->pixel_width;
34487 hlinfo->mouse_face_end_x = gx;
34488 }
34489 else
34490 {
34491 e = r->glyphs[TEXT_AREA];
34492 g = e + r->used[TEXT_AREA];
34493 for (gx = r->x ; e < g; ++e)
34494 {
34495 if (EQ (e->object, object)
34496 && startpos <= e->charpos && e->charpos < endpos)
34497 break;
34498 gx += e->pixel_width;
34499 }
34500 hlinfo->mouse_face_end_col = e - r->glyphs[TEXT_AREA];
34501 hlinfo->mouse_face_end_x = gx;
34502 }
34503 }
34504
34505 #ifdef HAVE_WINDOW_SYSTEM
34506
34507
34508
34509 static bool
34510 on_hot_spot_p (Lisp_Object hot_spot, int x, int y)
34511 {
34512 if (!CONSP (hot_spot))
34513 return false;
34514
34515 if (EQ (XCAR (hot_spot), Qrect))
34516 {
34517
34518 Lisp_Object rect = XCDR (hot_spot);
34519 Lisp_Object tem;
34520 if (!CONSP (rect))
34521 return false;
34522 if (!CONSP (XCAR (rect)))
34523 return false;
34524 if (!CONSP (XCDR (rect)))
34525 return false;
34526 if (!(tem = XCAR (XCAR (rect)), FIXNUMP (tem) && x >= XFIXNUM (tem)))
34527 return false;
34528 if (!(tem = XCDR (XCAR (rect)), FIXNUMP (tem) && y >= XFIXNUM (tem)))
34529 return false;
34530 if (!(tem = XCAR (XCDR (rect)), FIXNUMP (tem) && x <= XFIXNUM (tem)))
34531 return false;
34532 if (!(tem = XCDR (XCDR (rect)), FIXNUMP (tem) && y <= XFIXNUM (tem)))
34533 return false;
34534 return true;
34535 }
34536 else if (EQ (XCAR (hot_spot), Qcircle))
34537 {
34538
34539 Lisp_Object circ = XCDR (hot_spot);
34540 Lisp_Object lr, lx0, ly0;
34541 if (CONSP (circ)
34542 && CONSP (XCAR (circ))
34543 && (lr = XCDR (circ), NUMBERP (lr))
34544 && (lx0 = XCAR (XCAR (circ)), FIXNUMP (lx0))
34545 && (ly0 = XCDR (XCAR (circ)), FIXNUMP (ly0)))
34546 {
34547 double r = XFLOATINT (lr);
34548 double dx = XFIXNUM (lx0) - x;
34549 double dy = XFIXNUM (ly0) - y;
34550 return (dx * dx + dy * dy <= r * r);
34551 }
34552 }
34553 else if (EQ (XCAR (hot_spot), Qpoly))
34554 {
34555
34556 if (VECTORP (XCDR (hot_spot)))
34557 {
34558 struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot));
34559 Lisp_Object *poly = v->contents;
34560 ptrdiff_t n = v->header.size;
34561 ptrdiff_t i;
34562 bool inside = false;
34563 Lisp_Object lx, ly;
34564 int x0, y0;
34565
34566
34567 if (n < 6 || n & 1)
34568 return false;
34569
34570
34571
34572
34573
34574 if ((lx = poly[n-2], !FIXNUMP (lx))
34575 || (ly = poly[n-1], !FIXNUMP (lx)))
34576 return false;
34577 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34578 for (i = 0; i < n; i += 2)
34579 {
34580 int x1 = x0, y1 = y0;
34581 if ((lx = poly[i], !FIXNUMP (lx))
34582 || (ly = poly[i+1], !FIXNUMP (ly)))
34583 return false;
34584 x0 = XFIXNUM (lx), y0 = XFIXNUM (ly);
34585
34586
34587 if (x0 >= x)
34588 {
34589 if (x1 >= x)
34590 continue;
34591 }
34592 else if (x1 < x)
34593 continue;
34594 if (y > y0 && y > y1)
34595 continue;
34596 if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0))
34597 inside = !inside;
34598 }
34599 return inside;
34600 }
34601 }
34602 return false;
34603 }
34604
34605 Lisp_Object
34606 find_hot_spot (Lisp_Object map, int x, int y)
34607 {
34608 while (CONSP (map))
34609 {
34610 if (CONSP (XCAR (map))
34611 && on_hot_spot_p (XCAR (XCAR (map)), x, y))
34612 return XCAR (map);
34613 map = XCDR (map);
34614 }
34615
34616 return Qnil;
34617 }
34618
34619 DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map,
34620 3, 3, 0,
34621 doc:
34622
34623
34624
34625
34626
34627
34628
34629
34630 )
34631 (Lisp_Object map, Lisp_Object x, Lisp_Object y)
34632 {
34633 if (NILP (map))
34634 return Qnil;
34635
34636 CHECK_FIXNUM (x);
34637 CHECK_FIXNUM (y);
34638
34639 return find_hot_spot (map,
34640 clip_to_bounds (INT_MIN, XFIXNUM (x), INT_MAX),
34641 clip_to_bounds (INT_MIN, XFIXNUM (y), INT_MAX));
34642 }
34643 #endif
34644
34645
34646
34647 static void
34648 define_frame_cursor1 (struct frame *f, Emacs_Cursor cursor, Lisp_Object pointer)
34649 {
34650 #ifdef HAVE_WINDOW_SYSTEM
34651 if (!FRAME_WINDOW_P (f))
34652 return;
34653
34654
34655 if (EQ (track_mouse, Qdragging) || EQ (track_mouse, Qdropping)
34656 || EQ (track_mouse, Qdrag_source))
34657 return;
34658
34659 if (!NILP (pointer))
34660 {
34661 if (EQ (pointer, Qarrow))
34662 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34663 else if (EQ (pointer, Qhand))
34664 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34665 else if (EQ (pointer, Qtext))
34666 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
34667 else if (EQ (pointer, intern ("hdrag")))
34668 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
34669 else if (EQ (pointer, intern ("nhdrag")))
34670 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34671 # ifdef HAVE_X_WINDOWS
34672 else if (EQ (pointer, intern ("vdrag")))
34673 cursor = FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor;
34674 # endif
34675 else if (EQ (pointer, intern ("hourglass")))
34676 cursor = FRAME_OUTPUT_DATA (f)->hourglass_cursor;
34677 else if (EQ (pointer, Qmodeline))
34678 cursor = FRAME_OUTPUT_DATA (f)->modeline_cursor;
34679 else
34680 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34681 }
34682
34683 if (cursor != No_Cursor)
34684 FRAME_RIF (f)->define_frame_cursor (f, cursor);
34685 #endif
34686 }
34687
34688
34689
34690
34691
34692
34693
34694 static void
34695 note_mode_line_or_margin_highlight (Lisp_Object window, int x, int y,
34696 enum window_part area)
34697 {
34698 struct window *w = XWINDOW (window);
34699 struct frame *f = XFRAME (w->frame);
34700 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
34701 Emacs_Cursor cursor = No_Cursor;
34702 Lisp_Object pointer = Qnil;
34703 int dx, dy, width, height;
34704 ptrdiff_t charpos;
34705 Lisp_Object string, object = Qnil;
34706 Lisp_Object pos UNINIT;
34707 Lisp_Object mouse_face;
34708 int original_x_pixel = x;
34709 struct glyph * glyph = NULL, * row_start_glyph = NULL;
34710 struct glyph_row *row UNINIT;
34711
34712 if (area == ON_MODE_LINE || area == ON_HEADER_LINE || area == ON_TAB_LINE)
34713 {
34714 int x0;
34715 struct glyph *end;
34716
34717
34718
34719 string = mode_line_string (w, area, &x, &y, &charpos,
34720 &object, &dx, &dy, &width, &height);
34721
34722 row = (area == ON_MODE_LINE
34723 ? MATRIX_MODE_LINE_ROW (w->current_matrix)
34724 : (area == ON_TAB_LINE
34725 ? MATRIX_TAB_LINE_ROW (w->current_matrix)
34726 : MATRIX_HEADER_LINE_ROW (w->current_matrix)));
34727
34728
34729 if (row->mode_line_p && row->enabled_p)
34730 {
34731 glyph = row_start_glyph = row->glyphs[TEXT_AREA];
34732 end = glyph + row->used[TEXT_AREA];
34733
34734 for (x0 = original_x_pixel;
34735 glyph < end && x0 >= glyph->pixel_width;
34736 ++glyph)
34737 x0 -= glyph->pixel_width;
34738
34739 if (glyph >= end)
34740 glyph = NULL;
34741 }
34742 }
34743 else
34744 {
34745 x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w);
34746
34747
34748 string = marginal_area_string (w, area, &x, &y, &charpos,
34749 &object, &dx, &dy, &width, &height);
34750 }
34751
34752 Lisp_Object help = Qnil;
34753
34754 #ifdef HAVE_WINDOW_SYSTEM
34755 if (IMAGEP (object))
34756 {
34757 Lisp_Object image_map, hotspot;
34758 if ((image_map = plist_get (XCDR (object), QCmap),
34759 !NILP (image_map))
34760 && (hotspot = find_hot_spot (image_map, dx, dy),
34761 CONSP (hotspot))
34762 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
34763 {
34764 Lisp_Object plist;
34765
34766
34767
34768
34769 hotspot = XCDR (hotspot);
34770 if (CONSP (hotspot)
34771 && (plist = XCAR (hotspot), CONSP (plist)))
34772 {
34773 pointer = plist_get (plist, Qpointer);
34774 if (NILP (pointer))
34775 pointer = Qhand;
34776 help = plist_get (plist, Qhelp_echo);
34777 if (!NILP (help))
34778 {
34779 help_echo_string = help;
34780 XSETWINDOW (help_echo_window, w);
34781 help_echo_object = w->contents;
34782 help_echo_pos = charpos;
34783 }
34784 }
34785 }
34786 if (NILP (pointer))
34787 pointer = plist_get (XCDR (object), QCpointer);
34788 }
34789 #endif
34790
34791
34792
34793
34794 if (STRINGP (string))
34795 pos = make_fixnum (min (charpos, SCHARS (string) - 1));
34796
34797
34798
34799
34800
34801 if (STRINGP (string) || area == ON_MODE_LINE || area == ON_HEADER_LINE
34802 || area == ON_TAB_LINE)
34803 {
34804
34805
34806 if (NILP (help))
34807 {
34808 if (STRINGP (string))
34809 help = Fget_text_property (pos, Qhelp_echo, string);
34810
34811 if (!NILP (help))
34812 {
34813 help_echo_string = help;
34814 XSETWINDOW (help_echo_window, w);
34815 help_echo_object = string;
34816 help_echo_pos = charpos;
34817 }
34818 else if (area == ON_MODE_LINE
34819 && !NILP (w->mode_line_help_echo))
34820 {
34821 help_echo_string = w->mode_line_help_echo;
34822 XSETWINDOW (help_echo_window, w);
34823 help_echo_object = Qnil;
34824 help_echo_pos = -1;
34825 }
34826 }
34827
34828 #ifdef HAVE_WINDOW_SYSTEM
34829
34830 if (FRAME_WINDOW_P (f))
34831 {
34832 bool draggable = (! WINDOW_BOTTOMMOST_P (w)
34833 || minibuf_level
34834 || NILP (Vresize_mini_windows));
34835
34836 if (STRINGP (string))
34837 {
34838 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34839
34840 if (NILP (pointer))
34841 pointer = Fget_text_property (pos, Qpointer, string);
34842
34843
34844 if (NILP (pointer)
34845 && (area == ON_MODE_LINE || area == ON_HEADER_LINE
34846 || area == ON_TAB_LINE))
34847 {
34848 Lisp_Object map;
34849
34850 map = Fget_text_property (pos, Qlocal_map, string);
34851 if (!KEYMAPP (map))
34852 map = Fget_text_property (pos, Qkeymap, string);
34853 if (!KEYMAPP (map) && draggable && area == ON_MODE_LINE)
34854 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34855 }
34856 }
34857 else if (draggable && area == ON_MODE_LINE)
34858 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
34859 else if ((area == ON_MODE_LINE
34860 && WINDOW_BOTTOMMOST_P (w)
34861 && !FRAME_HAS_MINIBUF_P (f)
34862 && !NILP (Fframe_parameter
34863 (w->frame, Qdrag_with_mode_line)))
34864 || (((area == ON_HEADER_LINE
34865 && !NILP (Fframe_parameter
34866 (w->frame, Qdrag_with_header_line)))
34867 || (area == ON_TAB_LINE
34868 && !NILP (Fframe_parameter
34869 (w->frame, Qdrag_with_tab_line))))
34870 && WINDOW_TOPMOST_P (w)))
34871 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
34872 else
34873 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
34874 }
34875 #endif
34876 }
34877
34878
34879 bool mouse_face_shown = false;
34880
34881 if (STRINGP (string))
34882 {
34883 mouse_face = Fget_text_property (pos, Qmouse_face, string);
34884 if (!NILP (Vmouse_highlight) && !NILP (mouse_face)
34885 && ((area == ON_MODE_LINE) || (area == ON_HEADER_LINE)
34886 || (area == ON_TAB_LINE))
34887 && glyph)
34888 {
34889 Lisp_Object b, e;
34890
34891 struct glyph * tmp_glyph;
34892
34893 int gpos;
34894 int gseq_length;
34895 int total_pixel_width;
34896 ptrdiff_t begpos, endpos, ignore;
34897
34898 int vpos, hpos;
34899
34900 b = Fprevious_single_property_change (make_fixnum (charpos + 1),
34901 Qmouse_face, string, Qnil);
34902 if (NILP (b))
34903 begpos = 0;
34904 else
34905 begpos = XFIXNUM (b);
34906
34907 e = Fnext_single_property_change (pos, Qmouse_face, string, Qnil);
34908 if (NILP (e))
34909 endpos = SCHARS (string);
34910 else
34911 endpos = XFIXNUM (e);
34912
34913
34914
34915
34916
34917
34918
34919
34920
34921
34922
34923 tmp_glyph = row_start_glyph;
34924 while (tmp_glyph < glyph
34925 && (!(EQ (tmp_glyph->object, glyph->object)
34926 && begpos <= tmp_glyph->charpos
34927 && tmp_glyph->charpos < endpos)))
34928 tmp_glyph++;
34929 gpos = glyph - tmp_glyph;
34930
34931
34932
34933
34934
34935
34936 for (tmp_glyph = row->glyphs[TEXT_AREA] + row->used[TEXT_AREA] - 1;
34937 tmp_glyph > glyph
34938 && (!(EQ (tmp_glyph->object, glyph->object)
34939 && begpos <= tmp_glyph->charpos
34940 && tmp_glyph->charpos < endpos));
34941 tmp_glyph--)
34942 ;
34943 gseq_length = gpos + (tmp_glyph - glyph) + 1;
34944
34945
34946
34947 total_pixel_width = 0;
34948 for (tmp_glyph = glyph - gpos; tmp_glyph != glyph; tmp_glyph++)
34949 total_pixel_width += tmp_glyph->pixel_width;
34950
34951
34952
34953
34954 hpos = x - gpos;
34955 vpos = (area == ON_MODE_LINE
34956 ? (w->current_matrix)->nrows - 1
34957 : (area == ON_TAB_LINE
34958 ? 0
34959 : (w->current_matrix->tab_line_p
34960 ? 1
34961 : 0)));
34962
34963
34964
34965 if ( EQ (window, hlinfo->mouse_face_window)
34966 && (!row->reversed_p
34967 ? (hlinfo->mouse_face_beg_col <= hpos
34968 && hpos < hlinfo->mouse_face_end_col)
34969
34970 : (hlinfo->mouse_face_end_col <= hpos
34971 && hpos < hlinfo->mouse_face_beg_col))
34972 && hlinfo->mouse_face_beg_row == vpos )
34973 return;
34974
34975 if (clear_mouse_face (hlinfo))
34976 cursor = No_Cursor;
34977
34978 if (!row->reversed_p)
34979 {
34980 hlinfo->mouse_face_beg_col = hpos;
34981 hlinfo->mouse_face_beg_x = original_x_pixel
34982 - (total_pixel_width + dx);
34983 hlinfo->mouse_face_end_col = hpos + gseq_length;
34984 hlinfo->mouse_face_end_x = 0;
34985 }
34986 else
34987 {
34988
34989
34990 hlinfo->mouse_face_end_col = hpos;
34991 hlinfo->mouse_face_end_x = original_x_pixel
34992 - (total_pixel_width + dx);
34993 hlinfo->mouse_face_beg_col = hpos + gseq_length;
34994 hlinfo->mouse_face_beg_x = 0;
34995 }
34996
34997 hlinfo->mouse_face_beg_row = vpos;
34998 hlinfo->mouse_face_end_row = hlinfo->mouse_face_beg_row;
34999 hlinfo->mouse_face_past_end = false;
35000 hlinfo->mouse_face_window = window;
35001
35002 hlinfo->mouse_face_face_id =
35003 face_at_string_position (w, string, charpos, 0, &ignore,
35004 glyph->face_id, true, 0);
35005
35006 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35007 mouse_face_shown = true;
35008
35009 if (NILP (pointer))
35010 pointer = Qhand;
35011 }
35012 }
35013
35014
35015
35016 if ((area == ON_MODE_LINE || area == ON_HEADER_LINE
35017 || area == ON_TAB_LINE) && !mouse_face_shown)
35018 clear_mouse_face (hlinfo);
35019
35020 define_frame_cursor1 (f, cursor, pointer);
35021 }
35022
35023
35024
35025
35026
35027
35028
35029
35030
35031
35032 void
35033 note_mouse_highlight (struct frame *f, int x, int y)
35034 {
35035 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35036 enum window_part part = ON_NOTHING;
35037 Lisp_Object window;
35038 struct window *w;
35039 Emacs_Cursor cursor = No_Cursor;
35040 Lisp_Object pointer = Qnil;
35041 struct buffer *b;
35042
35043
35044 #if defined (HAVE_X_WINDOWS) || defined (HAVE_NS) || defined (MSDOS)
35045 if (popup_activated ())
35046 return;
35047 #endif
35048
35049 #if defined (HAVE_HAIKU)
35050 if (popup_activated_p)
35051 return;
35052 #endif
35053
35054 if (!f->glyphs_initialized_p
35055 || f->pointer_invisible)
35056 return;
35057
35058 hlinfo->mouse_face_mouse_x = x;
35059 hlinfo->mouse_face_mouse_y = y;
35060 hlinfo->mouse_face_mouse_frame = f;
35061
35062 if (hlinfo->mouse_face_defer)
35063 return;
35064
35065
35066 window = window_from_coordinates (f, x, y, &part, true, true);
35067
35068
35069 if (! EQ (window, hlinfo->mouse_face_window)
35070
35071 || (!NILP (hlinfo->mouse_face_window)
35072 && !NILP (window)
35073 && part != ON_TEXT
35074 && part != ON_MODE_LINE
35075 && part != ON_HEADER_LINE
35076 && part != ON_TAB_LINE))
35077 clear_mouse_face (hlinfo);
35078
35079
35080 help_echo_string = Qnil;
35081
35082
35083 if (!FRAME_WINDOW_P (f)
35084 && (y >= FRAME_MENU_BAR_LINES (f)
35085 && y < FRAME_MENU_BAR_LINES (f) + FRAME_TAB_BAR_LINES (f)))
35086 {
35087 int prop_idx;
35088 bool ignore;
35089 Lisp_Object caption = tty_get_tab_bar_item (f, x, &prop_idx, &ignore);
35090
35091 if (!NILP (caption))
35092 {
35093 help_echo_object = help_echo_window = Qnil;
35094 help_echo_pos = -1;
35095 help_echo_string = AREF (f->tab_bar_items,
35096 prop_idx * TAB_BAR_ITEM_NSLOTS
35097 + TAB_BAR_ITEM_HELP);
35098 if (NILP (help_echo_string))
35099 help_echo_string = caption;
35100 }
35101 }
35102
35103 #ifdef HAVE_WINDOW_SYSTEM
35104
35105
35106 if (FRAME_INTERNAL_BORDER_WIDTH (f) > 0
35107 && !NILP (get_frame_param (f, Qdrag_internal_border)))
35108 {
35109 enum internal_border_part part = frame_internal_border_part (f, x, y);
35110
35111 switch (part)
35112 {
35113 case INTERNAL_BORDER_NONE:
35114 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35115
35116 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35117 break;
35118 case INTERNAL_BORDER_LEFT_EDGE:
35119 cursor = FRAME_OUTPUT_DATA (f)->left_edge_cursor;
35120 break;
35121 case INTERNAL_BORDER_TOP_LEFT_CORNER:
35122 cursor = FRAME_OUTPUT_DATA (f)->top_left_corner_cursor;
35123 break;
35124 case INTERNAL_BORDER_TOP_EDGE:
35125 cursor = FRAME_OUTPUT_DATA (f)->top_edge_cursor;
35126 break;
35127 case INTERNAL_BORDER_TOP_RIGHT_CORNER:
35128 cursor = FRAME_OUTPUT_DATA (f)->top_right_corner_cursor;
35129 break;
35130 case INTERNAL_BORDER_RIGHT_EDGE:
35131 cursor = FRAME_OUTPUT_DATA (f)->right_edge_cursor;
35132 break;
35133 case INTERNAL_BORDER_BOTTOM_RIGHT_CORNER:
35134 cursor = FRAME_OUTPUT_DATA (f)->bottom_right_corner_cursor;
35135 break;
35136 case INTERNAL_BORDER_BOTTOM_EDGE:
35137 cursor = FRAME_OUTPUT_DATA (f)->bottom_edge_cursor;
35138 break;
35139 case INTERNAL_BORDER_BOTTOM_LEFT_CORNER:
35140 cursor = FRAME_OUTPUT_DATA (f)->bottom_left_corner_cursor;
35141 break;
35142 default:
35143
35144 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35145 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35146 }
35147
35148 if (cursor != FRAME_OUTPUT_DATA (f)->nontext_cursor)
35149 {
35150
35151 help_echo_string = build_string ("drag-mouse-1: resize frame");
35152 goto set_cursor;
35153 }
35154 }
35155 #endif
35156
35157
35158 if (!WINDOWP (window))
35159 return;
35160
35161
35162 w = XWINDOW (window);
35163 frame_to_window_pixel_xy (w, &x, &y);
35164
35165 #if defined (HAVE_WINDOW_SYSTEM)
35166
35167
35168 if (EQ (window, f->tab_bar_window))
35169 {
35170 note_tab_bar_highlight (f, x, y);
35171 if (tab_bar__dragging_in_progress)
35172 {
35173 cursor = FRAME_OUTPUT_DATA (f)->hand_cursor;
35174 goto set_cursor;
35175 }
35176 else
35177 return;
35178 }
35179 else
35180 {
35181
35182
35183
35184
35185 f->last_tab_bar_item = -1;
35186 }
35187 #endif
35188
35189 #if defined (HAVE_WINDOW_SYSTEM) && ! defined (HAVE_EXT_TOOL_BAR)
35190
35191
35192 if (EQ (window, f->tool_bar_window))
35193 {
35194 note_tool_bar_highlight (f, x, y);
35195 return;
35196 }
35197 #endif
35198
35199
35200 if (part == ON_MODE_LINE || part == ON_HEADER_LINE || part == ON_TAB_LINE
35201 || part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35202 {
35203 note_mode_line_or_margin_highlight (window, x, y, part);
35204
35205 #ifdef HAVE_WINDOW_SYSTEM
35206 if (part == ON_LEFT_MARGIN || part == ON_RIGHT_MARGIN)
35207 {
35208 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35209
35210 goto set_cursor;
35211 }
35212 else
35213 #endif
35214 return;
35215 }
35216
35217 #ifdef HAVE_WINDOW_SYSTEM
35218 if (part == ON_VERTICAL_BORDER)
35219 {
35220 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35221 help_echo_string = build_string ("drag-mouse-1: resize");
35222 goto set_cursor;
35223 }
35224 else if (part == ON_RIGHT_DIVIDER)
35225 {
35226 cursor = FRAME_OUTPUT_DATA (f)->horizontal_drag_cursor;
35227 help_echo_string = build_string ("drag-mouse-1: resize");
35228 goto set_cursor;
35229 }
35230 else if (part == ON_BOTTOM_DIVIDER)
35231 if (! WINDOW_BOTTOMMOST_P (w)
35232 || minibuf_level
35233 || NILP (Vresize_mini_windows))
35234 {
35235 cursor = FRAME_OUTPUT_DATA (f)->vertical_drag_cursor;
35236 help_echo_string = build_string ("drag-mouse-1: resize");
35237 goto set_cursor;
35238 }
35239 else
35240 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35241 else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE
35242 || part == ON_VERTICAL_SCROLL_BAR
35243 || part == ON_HORIZONTAL_SCROLL_BAR)
35244 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35245 else
35246 cursor = FRAME_OUTPUT_DATA (f)->text_cursor;
35247 #endif
35248
35249
35250
35251 b = XBUFFER (w->contents);
35252 if (part == ON_TEXT && w->window_end_valid && !window_outdated (w))
35253 {
35254 int hpos, vpos, dx, dy, area = LAST_AREA;
35255 ptrdiff_t pos;
35256 struct glyph *glyph;
35257 Lisp_Object object;
35258 Lisp_Object mouse_face = Qnil, position;
35259 Lisp_Object *overlay_vec = NULL;
35260 ptrdiff_t i, noverlays;
35261 struct buffer *obuf;
35262 ptrdiff_t obegv, ozv;
35263 bool same_region;
35264
35265
35266 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area);
35267
35268 #ifdef HAVE_WINDOW_SYSTEM
35269
35270 if (glyph != NULL && glyph->type == IMAGE_GLYPH)
35271 {
35272 struct image *img = IMAGE_OPT_FROM_ID (f, glyph->u.img_id);
35273 if (img != NULL && IMAGEP (img->spec))
35274 {
35275 Lisp_Object image_map, hotspot;
35276 if ((image_map = plist_get (XCDR (img->spec), QCmap),
35277 !NILP (image_map))
35278 && (hotspot = find_hot_spot (image_map,
35279 glyph->slice.img.x + dx,
35280 glyph->slice.img.y + dy),
35281 CONSP (hotspot))
35282 && (hotspot = XCDR (hotspot), CONSP (hotspot)))
35283 {
35284 Lisp_Object plist;
35285
35286
35287
35288
35289
35290 hotspot = XCDR (hotspot);
35291 if (CONSP (hotspot)
35292 && (plist = XCAR (hotspot), CONSP (plist)))
35293 {
35294 pointer = plist_get (plist, Qpointer);
35295 if (NILP (pointer))
35296 pointer = Qhand;
35297 help_echo_string = plist_get (plist, Qhelp_echo);
35298 if (!NILP (help_echo_string))
35299 {
35300 help_echo_window = window;
35301 help_echo_object = glyph->object;
35302 help_echo_pos = glyph->charpos;
35303 }
35304 }
35305 }
35306 if (NILP (pointer))
35307 pointer = plist_get (XCDR (img->spec), QCpointer);
35308 }
35309 }
35310 #endif
35311
35312
35313 if (glyph == NULL
35314 || area != TEXT_AREA
35315 || !MATRIX_ROW_DISPLAYS_TEXT_P (MATRIX_ROW (w->current_matrix, vpos))
35316
35317
35318
35319
35320
35321 || NILP (glyph->object)
35322
35323
35324
35325
35326 || (MATRIX_ROW (w->current_matrix, vpos)->reversed_p
35327 && glyph == MATRIX_ROW_GLYPH_START (w->current_matrix, vpos)
35328 && glyph->type == STRETCH_GLYPH
35329 && glyph->avoid_cursor_p))
35330 {
35331 if (clear_mouse_face (hlinfo))
35332 cursor = No_Cursor;
35333 if (FRAME_WINDOW_P (f) && NILP (pointer))
35334 {
35335 #ifdef HAVE_WINDOW_SYSTEM
35336 if (area != TEXT_AREA)
35337 cursor = FRAME_OUTPUT_DATA (f)->nontext_cursor;
35338 else
35339 pointer = Vvoid_text_area_pointer;
35340 #endif
35341 }
35342 goto set_cursor;
35343 }
35344
35345 pos = glyph->charpos;
35346 object = glyph->object;
35347 if (!STRINGP (object) && !BUFFERP (object))
35348 goto set_cursor;
35349
35350
35351 if (BUFFERP (object) && pos > BUF_Z (b))
35352 goto set_cursor;
35353
35354
35355
35356 obuf = current_buffer;
35357 current_buffer = b;
35358 obegv = BEGV;
35359 ozv = ZV;
35360 BEGV = BEG;
35361 ZV = Z;
35362
35363
35364 position = make_fixnum (pos);
35365
35366 USE_SAFE_ALLOCA;
35367
35368 if (BUFFERP (object))
35369 {
35370
35371 GET_OVERLAYS_AT (pos, overlay_vec, noverlays, NULL);
35372
35373 noverlays = sort_overlays (overlay_vec, noverlays, w);
35374 }
35375 else
35376 noverlays = 0;
35377
35378 if (NILP (Vmouse_highlight))
35379 {
35380 clear_mouse_face (hlinfo);
35381 goto check_help_echo;
35382 }
35383
35384 same_region = coords_in_mouse_face_p (w, hpos, vpos);
35385
35386 if (same_region)
35387 cursor = No_Cursor;
35388
35389
35390 if (! same_region
35391
35392
35393
35394
35395
35396 || (!hlinfo->mouse_face_hidden
35397 && OVERLAYP (hlinfo->mouse_face_overlay)
35398
35399 && OVERLAY_BUFFER (hlinfo->mouse_face_overlay)
35400 && mouse_face_overlay_overlaps (hlinfo->mouse_face_overlay)))
35401 {
35402
35403 Lisp_Object overlay = Qnil;
35404 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
35405 {
35406 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
35407 if (!NILP (mouse_face))
35408 overlay = overlay_vec[i];
35409 }
35410
35411
35412
35413 if (!NILP (overlay) && EQ (overlay, hlinfo->mouse_face_overlay))
35414 goto check_help_echo;
35415
35416
35417 if (clear_mouse_face (hlinfo))
35418 cursor = No_Cursor;
35419
35420
35421 hlinfo->mouse_face_overlay = overlay;
35422
35423
35424 if (NILP (overlay))
35425 mouse_face = Fget_text_property (position, Qmouse_face, object);
35426
35427
35428
35429 if (!NILP (mouse_face) && STRINGP (object))
35430 {
35431
35432
35433 Lisp_Object s, e;
35434 ptrdiff_t ignore;
35435
35436 s = Fprevious_single_property_change
35437 (make_fixnum (pos + 1), Qmouse_face, object, Qnil);
35438 e = Fnext_single_property_change
35439 (position, Qmouse_face, object, Qnil);
35440 if (NILP (s))
35441 s = make_fixnum (0);
35442 if (NILP (e))
35443 e = make_fixnum (SCHARS (object));
35444 mouse_face_from_string_pos (w, hlinfo, object,
35445 XFIXNUM (s), XFIXNUM (e));
35446 hlinfo->mouse_face_past_end = false;
35447 hlinfo->mouse_face_window = window;
35448 hlinfo->mouse_face_face_id
35449 = face_at_string_position (w, object, pos, 0, &ignore,
35450 glyph->face_id, true, 0);
35451 show_mouse_face (hlinfo, DRAW_MOUSE_FACE);
35452 cursor = No_Cursor;
35453 }
35454 else
35455 {
35456
35457
35458 Lisp_Object buffer UNINIT;
35459 Lisp_Object disp_string UNINIT;
35460
35461 if (STRINGP (object))
35462 {
35463
35464
35465 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
35466 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35467 pos = string_buffer_position (object, start);
35468 if (pos > 0)
35469 {
35470 mouse_face = get_char_property_and_overlay
35471 (make_fixnum (pos), Qmouse_face, w->contents, &overlay);
35472 buffer = w->contents;
35473 disp_string = object;
35474 }
35475 }
35476 else
35477 {
35478 buffer = object;
35479 disp_string = Qnil;
35480 }
35481
35482 if (!NILP (mouse_face))
35483 {
35484 Lisp_Object before, after;
35485 Lisp_Object before_string, after_string;
35486
35487
35488
35489
35490
35491
35492
35493
35494
35495
35496 Lisp_Object lim1
35497 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35498 ? Fmarker_position (w->start)
35499 : Qnil;
35500 Lisp_Object lim2
35501 = NILP (BVAR (XBUFFER (buffer), bidi_display_reordering))
35502 ? make_fixnum (BUF_Z (XBUFFER (buffer))
35503 - w->window_end_pos)
35504 : Qnil;
35505
35506 if (NILP (overlay))
35507 {
35508
35509 before = Fprevious_single_property_change
35510 (make_fixnum (pos + 1), Qmouse_face, buffer, lim1);
35511 after = Fnext_single_property_change
35512 (make_fixnum (pos), Qmouse_face, buffer, lim2);
35513 before_string = after_string = Qnil;
35514 }
35515 else
35516 {
35517
35518 before = Foverlay_start (overlay);
35519 after = Foverlay_end (overlay);
35520 before_string = Foverlay_get (overlay, Qbefore_string);
35521 after_string = Foverlay_get (overlay, Qafter_string);
35522
35523 if (!STRINGP (before_string)) before_string = Qnil;
35524 if (!STRINGP (after_string)) after_string = Qnil;
35525 }
35526
35527 mouse_face_from_buffer_pos (window, hlinfo, pos,
35528 NILP (before)
35529 ? 1
35530 : XFIXNAT (before),
35531 NILP (after)
35532 ? BUF_Z (XBUFFER (buffer))
35533 : XFIXNAT (after),
35534 before_string, after_string,
35535 disp_string);
35536 cursor = No_Cursor;
35537 }
35538 }
35539 }
35540
35541 check_help_echo:
35542
35543
35544 if (NILP (help_echo_string)) {
35545 Lisp_Object help, overlay;
35546
35547
35548 help = overlay = Qnil;
35549 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
35550 {
35551 overlay = overlay_vec[i];
35552 help = Foverlay_get (overlay, Qhelp_echo);
35553 }
35554
35555 if (!NILP (help))
35556 {
35557 help_echo_string = help;
35558 help_echo_window = window;
35559 help_echo_object = overlay;
35560 help_echo_pos = pos;
35561 }
35562 else
35563 {
35564 Lisp_Object obj = glyph->object;
35565 ptrdiff_t charpos = glyph->charpos;
35566
35567
35568 if (STRINGP (obj)
35569 && charpos >= 0
35570 && charpos < SCHARS (obj))
35571 {
35572 help = Fget_text_property (make_fixnum (charpos),
35573 Qhelp_echo, obj);
35574 if (NILP (help))
35575 {
35576
35577
35578 struct glyph_row *r
35579 = MATRIX_ROW (w->current_matrix, vpos);
35580 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35581 ptrdiff_t p = string_buffer_position (obj, start);
35582 if (p > 0)
35583 {
35584 help = Fget_char_property (make_fixnum (p),
35585 Qhelp_echo, w->contents);
35586 if (!NILP (help))
35587 {
35588 charpos = p;
35589 obj = w->contents;
35590 }
35591 }
35592 }
35593 }
35594 else if (BUFFERP (obj)
35595 && charpos >= BEGV
35596 && charpos < ZV)
35597 help = Fget_text_property (make_fixnum (charpos), Qhelp_echo,
35598 obj);
35599
35600 if (!NILP (help))
35601 {
35602 help_echo_string = help;
35603 help_echo_window = window;
35604 help_echo_object = obj;
35605 help_echo_pos = charpos;
35606 }
35607 }
35608 }
35609
35610 #ifdef HAVE_WINDOW_SYSTEM
35611
35612 if (FRAME_WINDOW_P (f) && NILP (pointer))
35613 {
35614
35615 for (i = noverlays - 1; i >= 0 && NILP (pointer); --i)
35616 pointer = Foverlay_get (overlay_vec[i], Qpointer);
35617
35618 if (NILP (pointer))
35619 {
35620 Lisp_Object obj = glyph->object;
35621 ptrdiff_t charpos = glyph->charpos;
35622
35623
35624 if (STRINGP (obj)
35625 && charpos >= 0
35626 && charpos < SCHARS (obj))
35627 {
35628 pointer = Fget_text_property (make_fixnum (charpos),
35629 Qpointer, obj);
35630 if (NILP (pointer))
35631 {
35632
35633
35634 struct glyph_row *r
35635 = MATRIX_ROW (w->current_matrix, vpos);
35636 ptrdiff_t start = MATRIX_ROW_START_CHARPOS (r);
35637 ptrdiff_t p = string_buffer_position (obj, start);
35638 if (p > 0)
35639 pointer = Fget_char_property (make_fixnum (p),
35640 Qpointer, w->contents);
35641 }
35642 }
35643 else if (BUFFERP (obj)
35644 && charpos >= BEGV
35645 && charpos < ZV)
35646 pointer = Fget_text_property (make_fixnum (charpos),
35647 Qpointer, obj);
35648 }
35649 }
35650 #endif
35651
35652 BEGV = obegv;
35653 ZV = ozv;
35654 current_buffer = obuf;
35655 SAFE_FREE ();
35656 }
35657
35658 set_cursor:
35659 define_frame_cursor1 (f, cursor, pointer);
35660 }
35661
35662
35663
35664
35665
35666
35667
35668 void
35669 gui_clear_window_mouse_face (struct window *w)
35670 {
35671 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
35672 Lisp_Object window;
35673
35674 block_input ();
35675 XSETWINDOW (window, w);
35676 if (EQ (window, hlinfo->mouse_face_window))
35677 clear_mouse_face (hlinfo);
35678 unblock_input ();
35679 }
35680
35681
35682
35683
35684
35685
35686 void
35687 cancel_mouse_face (struct frame *f)
35688 {
35689 Lisp_Object window;
35690 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
35691
35692 window = hlinfo->mouse_face_window;
35693 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
35694 reset_mouse_highlight (hlinfo);
35695 }
35696
35697
35698
35699
35700
35701
35702
35703 #ifdef HAVE_WINDOW_SYSTEM
35704
35705
35706
35707
35708 static void
35709 expose_area (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r,
35710 enum glyph_row_area area)
35711 {
35712 struct glyph *first = row->glyphs[area];
35713 struct glyph *end = row->glyphs[area] + row->used[area];
35714 struct glyph *last;
35715 int first_x, start_x, x;
35716
35717 if (area == TEXT_AREA && row->fill_line_p)
35718
35719 draw_glyphs (w, row->x, row, area,
35720 0, row->used[area],
35721 DRAW_NORMAL_TEXT, 0);
35722 else
35723 {
35724
35725
35726
35727 start_x = window_box_left_offset (w, area);
35728 x = start_x;
35729 if (area == TEXT_AREA)
35730 x += row->x;
35731
35732
35733 while (first < end
35734 && x + first->pixel_width < r->x)
35735 {
35736 x += first->pixel_width;
35737 ++first;
35738 }
35739
35740
35741 last = first;
35742 first_x = x;
35743
35744
35745
35746 int r_end = r->x + r->width;
35747 while (last < end && x < r_end)
35748 {
35749 x += last->pixel_width;
35750 ++last;
35751 }
35752
35753
35754 if (last > first)
35755 draw_glyphs (w, first_x - start_x, row, area,
35756 first - row->glyphs[area], last - row->glyphs[area],
35757 DRAW_NORMAL_TEXT, 0);
35758 }
35759 }
35760
35761
35762
35763
35764
35765
35766 static bool
35767 expose_line (struct window *w, struct glyph_row *row, const Emacs_Rectangle *r)
35768 {
35769 eassert (row->enabled_p);
35770
35771 if (row->mode_line_p || w->pseudo_window_p)
35772 draw_glyphs (w, 0, row, TEXT_AREA,
35773 0, row->used[TEXT_AREA],
35774 DRAW_NORMAL_TEXT, 0);
35775 else
35776 {
35777 if (row->used[LEFT_MARGIN_AREA])
35778 expose_area (w, row, r, LEFT_MARGIN_AREA);
35779 if (row->used[TEXT_AREA])
35780 expose_area (w, row, r, TEXT_AREA);
35781 if (row->used[RIGHT_MARGIN_AREA])
35782 expose_area (w, row, r, RIGHT_MARGIN_AREA);
35783 draw_row_fringe_bitmaps (w, row);
35784 }
35785
35786 return row->mouse_face_p;
35787 }
35788
35789
35790
35791
35792
35793
35794
35795
35796
35797
35798 static void
35799 expose_overlaps (struct window *w,
35800 struct glyph_row *first_overlapping_row,
35801 struct glyph_row *last_overlapping_row,
35802 const Emacs_Rectangle *r)
35803 {
35804 struct glyph_row *row;
35805
35806 for (row = first_overlapping_row; row <= last_overlapping_row; ++row)
35807 if (row->overlapping_p)
35808 {
35809 eassert (row->enabled_p && !row->mode_line_p);
35810
35811 row->clip = r;
35812 if (row->used[LEFT_MARGIN_AREA])
35813 gui_fix_overlapping_area (w, row, LEFT_MARGIN_AREA, OVERLAPS_BOTH);
35814
35815 if (row->used[TEXT_AREA])
35816 gui_fix_overlapping_area (w, row, TEXT_AREA, OVERLAPS_BOTH);
35817
35818 if (row->used[RIGHT_MARGIN_AREA])
35819 gui_fix_overlapping_area (w, row, RIGHT_MARGIN_AREA, OVERLAPS_BOTH);
35820 row->clip = NULL;
35821 }
35822 }
35823
35824
35825
35826
35827 static bool
35828 phys_cursor_in_rect_p (struct window *w, const Emacs_Rectangle *r)
35829 {
35830 Emacs_Rectangle cr, result;
35831 struct glyph *cursor_glyph;
35832 struct glyph_row *row;
35833
35834 if (w->phys_cursor.vpos >= 0
35835 && w->phys_cursor.vpos < w->current_matrix->nrows
35836 && (row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos),
35837 row->enabled_p)
35838 && row->cursor_in_fringe_p)
35839 {
35840
35841 cr.x = window_box_right_offset (w,
35842 (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
35843 ? RIGHT_MARGIN_AREA
35844 : TEXT_AREA));
35845 cr.y = row->y;
35846 cr.width = WINDOW_RIGHT_FRINGE_WIDTH (w);
35847 cr.height = row->height;
35848 return gui_intersect_rectangles (&cr, r, &result);
35849 }
35850
35851 cursor_glyph = get_phys_cursor_glyph (w);
35852 if (cursor_glyph)
35853 {
35854
35855
35856 cr.x = window_box_left_offset (w, TEXT_AREA) + w->phys_cursor.x;
35857 cr.y = w->phys_cursor.y;
35858 cr.width = cursor_glyph->pixel_width;
35859 cr.height = w->phys_cursor_height;
35860
35861
35862 return gui_intersect_rectangles (&cr, r, &result);
35863 }
35864
35865 return false;
35866 }
35867
35868
35869
35870
35871
35872
35873 void
35874 gui_draw_vertical_border (struct window *w)
35875 {
35876 struct frame *f = XFRAME (WINDOW_FRAME (w));
35877
35878
35879
35880
35881
35882
35883
35884
35885
35886 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f) || FRAME_RIGHT_DIVIDER_WIDTH (f))
35887 return;
35888
35889
35890
35891
35892 if (!WINDOW_RIGHTMOST_P (w)
35893 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
35894 {
35895 int x0, x1, y0, y1;
35896
35897 window_box_edges (w, &x0, &y0, &x1, &y1);
35898 y1 -= 1;
35899
35900 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
35901 x1 -= 1;
35902
35903 FRAME_RIF (f)->draw_vertical_window_border (w, x1, y0, y1);
35904 }
35905
35906 if (!WINDOW_LEFTMOST_P (w)
35907 && !WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w))
35908 {
35909 int x0, x1, y0, y1;
35910
35911 window_box_edges (w, &x0, &y0, &x1, &y1);
35912 y1 -= 1;
35913
35914 if (WINDOW_LEFT_FRINGE_WIDTH (w) == 0)
35915 x0 -= 1;
35916
35917 FRAME_RIF (f)->draw_vertical_window_border (w, x0, y0, y1);
35918 }
35919 }
35920
35921
35922
35923
35924 void
35925 gui_draw_right_divider (struct window *w)
35926 {
35927 struct frame *f = WINDOW_XFRAME (w);
35928
35929 if (w->mini || w->pseudo_window_p)
35930 return;
35931 else if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
35932 {
35933 int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
35934 int x1 = WINDOW_RIGHT_EDGE_X (w);
35935 int y0 = WINDOW_TOP_EDGE_Y (w);
35936 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
35937
35938
35939
35940 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w)
35941 && !NILP (w->parent)
35942 && WINDOW_HORIZONTAL_COMBINATION_P (XWINDOW (w->parent))
35943 && !NILP (w->next))
35944 y1 -= WINDOW_BOTTOM_DIVIDER_WIDTH (w);
35945
35946 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
35947 }
35948 }
35949
35950 static void
35951 gui_draw_bottom_divider (struct window *w)
35952 {
35953 struct frame *f = XFRAME (WINDOW_FRAME (w));
35954
35955 if (w->mini || w->pseudo_window_p)
35956 return;
35957 else if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
35958 {
35959 int x0 = WINDOW_LEFT_EDGE_X (w);
35960 int x1 = WINDOW_RIGHT_EDGE_X (w);
35961 int y0 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
35962 int y1 = WINDOW_BOTTOM_EDGE_Y (w);
35963 struct window *p = !NILP (w->parent) ? XWINDOW (w->parent) : NULL;
35964
35965
35966
35967 if (WINDOW_RIGHT_DIVIDER_WIDTH (w)
35968 && p
35969 && ((WINDOW_VERTICAL_COMBINATION_P (p)
35970 && !NILP (w->next))
35971 || (WINDOW_HORIZONTAL_COMBINATION_P (p)
35972 && NILP (w->next)
35973 && !NILP (p->parent)
35974 && WINDOW_VERTICAL_COMBINATION_P (XWINDOW (p->parent))
35975 && !NILP (XWINDOW (p->parent)->next))))
35976 x1 -= WINDOW_RIGHT_DIVIDER_WIDTH (w);
35977
35978 FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
35979 }
35980 }
35981
35982
35983
35984
35985
35986
35987 static bool
35988 expose_window (struct window *w, const Emacs_Rectangle *fr)
35989 {
35990 struct frame *f = XFRAME (w->frame);
35991 Emacs_Rectangle wr, r;
35992 bool mouse_face_overwritten_p = false;
35993
35994
35995
35996
35997
35998 if (w->current_matrix == NULL)
35999 return false;
36000
36001
36002
36003
36004 if (w->must_be_updated_p)
36005 {
36006 SET_FRAME_GARBAGED (f);
36007 return false;
36008 }
36009
36010
36011 wr.x = WINDOW_LEFT_EDGE_X (w);
36012 wr.y = WINDOW_TOP_EDGE_Y (w);
36013 wr.width = WINDOW_PIXEL_WIDTH (w);
36014 wr.height = WINDOW_PIXEL_HEIGHT (w);
36015
36016 if (gui_intersect_rectangles (fr, &wr, &r))
36017 {
36018 int yb = window_text_bottom_y (w);
36019 struct glyph_row *row;
36020 struct glyph_row *first_overlapping_row, *last_overlapping_row;
36021
36022 redisplay_trace ("expose_window (%d, %d, %u, %u)\n",
36023 r.x, r.y, r.width, r.height);
36024
36025
36026 r.x -= WINDOW_LEFT_EDGE_X (w);
36027 r.y -= WINDOW_TOP_EDGE_Y (w);
36028
36029
36030 bool cursor_cleared_p = (!w->pseudo_window_p
36031 && phys_cursor_in_rect_p (w, &r));
36032 if (cursor_cleared_p)
36033 gui_clear_cursor (w);
36034
36035
36036
36037
36038
36039
36040 bool phys_cursor_on_p = w->phys_cursor_on_p;
36041
36042
36043
36044
36045 int r_bottom = r.y + r.height;
36046
36047
36048
36049
36050
36051 bool buffer_changed = false;
36052 struct buffer *oldbuf = current_buffer;
36053 if (!w->pseudo_window_p)
36054 {
36055 set_buffer_internal_1 (XBUFFER (w->contents));
36056 buffer_changed = true;
36057 }
36058
36059
36060 first_overlapping_row = last_overlapping_row = NULL;
36061 for (row = w->current_matrix->rows;
36062 row->enabled_p;
36063 ++row)
36064 {
36065 int y0 = row->y;
36066 int y1 = MATRIX_ROW_BOTTOM_Y (row);
36067
36068 if ((y0 >= r.y && y0 < r_bottom)
36069 || (y1 > r.y && y1 < r_bottom)
36070 || (r.y >= y0 && r.y < y1)
36071 || (r_bottom > y0 && r_bottom < y1))
36072 {
36073
36074
36075 if (row->overlapping_p && !row->mode_line_p)
36076 {
36077 if (first_overlapping_row == NULL)
36078 first_overlapping_row = row;
36079 last_overlapping_row = row;
36080 }
36081
36082 row->clip = fr;
36083 if (expose_line (w, row, &r))
36084 mouse_face_overwritten_p = true;
36085 row->clip = NULL;
36086 }
36087 else if (row->overlapping_p)
36088 {
36089
36090 if (y0 < r.y
36091 ? y0 + row->phys_height > r.y
36092 : y0 + row->ascent - row->phys_ascent < r.y +r.height)
36093 {
36094 if (first_overlapping_row == NULL)
36095 first_overlapping_row = row;
36096 last_overlapping_row = row;
36097 }
36098 }
36099
36100 if (y1 >= yb)
36101 break;
36102 }
36103
36104 if (buffer_changed)
36105 set_buffer_internal_1 (oldbuf);
36106
36107
36108 if (window_wants_mode_line (w)
36109 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
36110 row->enabled_p)
36111 && row->y < r_bottom)
36112 {
36113 if (expose_line (w, row, &r))
36114 mouse_face_overwritten_p = true;
36115 }
36116
36117 if (!w->pseudo_window_p)
36118 {
36119
36120 if (first_overlapping_row)
36121 expose_overlaps (w, first_overlapping_row, last_overlapping_row,
36122 fr);
36123
36124
36125 if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
36126 gui_draw_right_divider (w);
36127 else
36128 gui_draw_vertical_border (w);
36129
36130 if (WINDOW_BOTTOM_DIVIDER_WIDTH (w))
36131 gui_draw_bottom_divider (w);
36132
36133
36134 if (cursor_cleared_p
36135 || (phys_cursor_on_p && !w->phys_cursor_on_p))
36136 update_window_cursor (w, true);
36137 }
36138 }
36139
36140 return mouse_face_overwritten_p;
36141 }
36142
36143
36144
36145
36146
36147
36148
36149 static bool
36150 expose_window_tree (struct window *w, const Emacs_Rectangle *r)
36151 {
36152 struct frame *f = XFRAME (w->frame);
36153 bool mouse_face_overwritten_p = false;
36154
36155 while (w && !FRAME_GARBAGED_P (f))
36156 {
36157 mouse_face_overwritten_p
36158 |= (WINDOWP (w->contents)
36159 ? expose_window_tree (XWINDOW (w->contents), r)
36160 : expose_window (w, r));
36161
36162 w = NILP (w->next) ? NULL : XWINDOW (w->next);
36163 }
36164
36165 return mouse_face_overwritten_p;
36166 }
36167
36168
36169
36170
36171
36172
36173
36174
36175 void
36176 expose_frame (struct frame *f, int x, int y, int w, int h)
36177 {
36178 Emacs_Rectangle r;
36179 bool mouse_face_overwritten_p = false;
36180
36181 if (FRAME_GARBAGED_P (f))
36182 {
36183 redisplay_trace ("expose_frame garbaged\n");
36184 return;
36185 }
36186
36187
36188
36189
36190 if (FRAME_FACE_CACHE (f) == NULL
36191 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
36192 {
36193 redisplay_trace ("expose_frame no faces\n");
36194 return;
36195 }
36196
36197 if (w == 0 || h == 0)
36198 {
36199 r.x = r.y = 0;
36200 r.width = FRAME_TEXT_WIDTH (f);
36201 r.height = FRAME_TEXT_HEIGHT (f);
36202 }
36203 else
36204 {
36205 r.x = x;
36206 r.y = y;
36207 r.width = w;
36208 r.height = h;
36209 }
36210
36211 redisplay_trace ("expose_frame (%d, %d, %u, %u)\n",
36212 r.x, r.y, r.width, r.height);
36213 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
36214
36215 if (WINDOWP (f->tab_bar_window))
36216 mouse_face_overwritten_p
36217 |= expose_window (XWINDOW (f->tab_bar_window), &r);
36218
36219 #ifndef HAVE_EXT_TOOL_BAR
36220 if (WINDOWP (f->tool_bar_window))
36221 mouse_face_overwritten_p
36222 |= expose_window (XWINDOW (f->tool_bar_window), &r);
36223 #endif
36224
36225 #ifdef HAVE_X_WINDOWS
36226 #ifndef MSDOS
36227 #if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
36228 if (WINDOWP (f->menu_bar_window))
36229 mouse_face_overwritten_p
36230 |= expose_window (XWINDOW (f->menu_bar_window), &r);
36231 #endif
36232 #endif
36233 #endif
36234
36235
36236
36237
36238
36239
36240
36241
36242
36243
36244
36245
36246
36247
36248 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
36249 {
36250 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
36251 if (f == hlinfo->mouse_face_mouse_frame)
36252 {
36253 int mouse_x = hlinfo->mouse_face_mouse_x;
36254 int mouse_y = hlinfo->mouse_face_mouse_y;
36255 clear_mouse_face (hlinfo);
36256 note_mouse_highlight (f, mouse_x, mouse_y);
36257 }
36258 }
36259 }
36260
36261
36262
36263
36264
36265
36266
36267 bool
36268 gui_intersect_rectangles (const Emacs_Rectangle *r1, const Emacs_Rectangle *r2,
36269 Emacs_Rectangle *result)
36270 {
36271 const Emacs_Rectangle *left, *right;
36272 const Emacs_Rectangle *upper, *lower;
36273 bool intersection_p = false;
36274
36275
36276 if (r1->x < r2->x)
36277 left = r1, right = r2;
36278 else
36279 left = r2, right = r1;
36280
36281
36282
36283 if (right->x <= left->x + left->width)
36284 {
36285 result->x = right->x;
36286
36287
36288
36289 result->width = (min (left->x + left->width, right->x + right->width)
36290 - result->x);
36291
36292
36293 if (r1->y < r2->y)
36294 upper = r1, lower = r2;
36295 else
36296 upper = r2, lower = r1;
36297
36298
36299
36300 if (lower->y <= upper->y + upper->height)
36301 {
36302 result->y = lower->y;
36303
36304
36305
36306 result->height = (min (lower->y + lower->height,
36307 upper->y + upper->height)
36308 - result->y);
36309 intersection_p = true;
36310 }
36311 }
36312
36313 return intersection_p;
36314 }
36315
36316 #endif
36317
36318
36319
36320
36321
36322
36323 void
36324 syms_of_xdisp (void)
36325 {
36326 Vwith_echo_area_save_vector = Qnil;
36327 staticpro (&Vwith_echo_area_save_vector);
36328
36329 Vmessage_stack = Qnil;
36330 staticpro (&Vmessage_stack);
36331
36332
36333 DEFSYM (Qinhibit_redisplay, "inhibit-redisplay");
36334
36335 DEFSYM (Qredisplay_internal_xC_functionx, "redisplay_internal (C function)");
36336
36337 DEFVAR_BOOL ("scroll-minibuffer-conservatively",
36338 scroll_minibuffer_conservatively,
36339 doc:
36340
36341 );
36342 scroll_minibuffer_conservatively = true;
36343
36344 DEFVAR_BOOL ("inhibit-message", inhibit_message,
36345 doc:
36346
36347
36348
36349
36350
36351 );
36352 inhibit_message = false;
36353
36354 message_dolog_marker1 = Fmake_marker ();
36355 staticpro (&message_dolog_marker1);
36356 message_dolog_marker2 = Fmake_marker ();
36357 staticpro (&message_dolog_marker2);
36358 message_dolog_marker3 = Fmake_marker ();
36359 staticpro (&message_dolog_marker3);
36360
36361 defsubr (&Sset_buffer_redisplay);
36362 #ifdef GLYPH_DEBUG
36363 defsubr (&Sdump_frame_glyph_matrix);
36364 defsubr (&Sdump_glyph_matrix);
36365 defsubr (&Sdump_glyph_row);
36366 defsubr (&Sdump_tab_bar_row);
36367 defsubr (&Sdump_tool_bar_row);
36368 defsubr (&Strace_redisplay);
36369 defsubr (&Strace_to_stderr);
36370 #endif
36371 #ifdef HAVE_WINDOW_SYSTEM
36372 defsubr (&Stab_bar_height);
36373 defsubr (&Stool_bar_height);
36374 defsubr (&Slookup_image_map);
36375 #endif
36376 defsubr (&Sline_pixel_height);
36377 defsubr (&Sformat_mode_line);
36378 defsubr (&Sinvisible_p);
36379 defsubr (&Scurrent_bidi_paragraph_direction);
36380 defsubr (&Swindow_text_pixel_size);
36381 defsubr (&Sbuffer_text_pixel_size);
36382 defsubr (&Smove_point_visually);
36383 defsubr (&Sbidi_find_overridden_directionality);
36384 defsubr (&Sdisplay__line_is_continued_p);
36385 defsubr (&Sget_display_property);
36386 defsubr (&Slong_line_optimizations_p);
36387
36388 DEFSYM (Qmenu_bar_update_hook, "menu-bar-update-hook");
36389 DEFSYM (Qoverriding_terminal_local_map, "overriding-terminal-local-map");
36390 DEFSYM (Qoverriding_local_map, "overriding-local-map");
36391 DEFSYM (Qwindow_scroll_functions, "window-scroll-functions");
36392 DEFSYM (Qinhibit_point_motion_hooks, "inhibit-point-motion-hooks");
36393 DEFSYM (Qeval, "eval");
36394 DEFSYM (QCdata, ":data");
36395
36396
36397 DEFSYM (Qdisplay, "display");
36398 DEFSYM (Qspace_width, "space-width");
36399 DEFSYM (Qraise, "raise");
36400 DEFSYM (Qslice, "slice");
36401 DEFSYM (Qspace, "space");
36402 DEFSYM (Qmargin, "margin");
36403 DEFSYM (Qpointer, "pointer");
36404 DEFSYM (Qleft_margin, "left-margin");
36405 DEFSYM (Qright_margin, "right-margin");
36406 DEFSYM (Qcenter, "center");
36407 DEFSYM (Qline_height, "line-height");
36408 DEFSYM (QCalign_to, ":align-to");
36409 DEFSYM (QCrelative_width, ":relative-width");
36410 DEFSYM (QCrelative_height, ":relative-height");
36411 DEFSYM (QCeval, ":eval");
36412 DEFSYM (QCpropertize, ":propertize");
36413 DEFSYM (QCfile, ":file");
36414 DEFSYM (Qfontified, "fontified");
36415 DEFSYM (Qfontification_functions, "fontification-functions");
36416 DEFSYM (Qlong_line_optimizations_in_fontification_functions,
36417 "long-line-optimizations-in-fontification-functions");
36418
36419
36420
36421 DEFSYM (Qdisable_eval, "disable-eval");
36422
36423
36424 DEFSYM (Qtrailing_whitespace, "trailing-whitespace");
36425
36426
36427 DEFSYM (Qline_number, "line-number");
36428 DEFSYM (Qline_number_current_line, "line-number-current-line");
36429 DEFSYM (Qline_number_major_tick, "line-number-major-tick");
36430 DEFSYM (Qline_number_minor_tick, "line-number-minor-tick");
36431
36432 DEFSYM (Qdisplay_line_numbers_disable, "display-line-numbers-disable");
36433
36434
36435 DEFSYM (Qfill_column_indicator, "fill-column-indicator");
36436
36437
36438 DEFSYM (Qescape_glyph, "escape-glyph");
36439
36440
36441
36442 DEFSYM (Qnobreak_space, "nobreak-space");
36443 DEFSYM (Qnobreak_hyphen, "nobreak-hyphen");
36444
36445
36446
36447 DEFSYM (Qimage, "image");
36448
36449
36450 DEFSYM (Qtext, "text");
36451 DEFSYM (Qboth, "both");
36452 DEFSYM (Qboth_horiz, "both-horiz");
36453 DEFSYM (Qtext_image_horiz, "text-image-horiz");
36454
36455
36456 DEFSYM (QCmap, ":map");
36457 DEFSYM (QCpointer, ":pointer");
36458 DEFSYM (Qrect, "rect");
36459 DEFSYM (Qcircle, "circle");
36460 DEFSYM (Qpoly, "poly");
36461
36462 DEFSYM (Qinhibit_menubar_update, "inhibit-menubar-update");
36463
36464 DEFSYM (Qgrow_only, "grow-only");
36465 DEFSYM (Qinhibit_eval_during_redisplay, "inhibit-eval-during-redisplay");
36466 DEFSYM (Qposition, "position");
36467 DEFSYM (Qbuffer_position, "buffer-position");
36468 DEFSYM (Qobject, "object");
36469
36470
36471 DEFSYM (Qbar, "bar");
36472 DEFSYM (Qhbar, "hbar");
36473 DEFSYM (Qbox, "box");
36474 DEFSYM (Qhollow, "hollow");
36475
36476
36477 DEFSYM (Qhand, "hand");
36478 DEFSYM (Qarrow, "arrow");
36479
36480
36481 DEFSYM (Qdragging, "dragging");
36482 DEFSYM (Qdropping, "dropping");
36483 DEFSYM (Qdrag_source, "drag-source");
36484
36485 DEFSYM (Qdrag_with_mode_line, "drag-with-mode-line");
36486 DEFSYM (Qdrag_with_header_line, "drag-with-header-line");
36487 DEFSYM (Qdrag_with_tab_line, "drag-with-tab-line");
36488
36489 DEFSYM (Qinhibit_free_realized_faces, "inhibit-free-realized-faces");
36490
36491 list_of_error = list1 (Qerror);
36492 staticpro (&list_of_error);
36493
36494
36495
36496
36497
36498 DEFSYM (Qlast_arrow_position, "last-arrow-position");
36499 DEFSYM (Qlast_arrow_string, "last-arrow-string");
36500
36501
36502
36503 DEFSYM (Qoverlay_arrow_string, "overlay-arrow-string");
36504 DEFSYM (Qoverlay_arrow_bitmap, "overlay-arrow-bitmap");
36505
36506 echo_buffer[0] = echo_buffer[1] = Qnil;
36507 staticpro (&echo_buffer[0]);
36508 staticpro (&echo_buffer[1]);
36509
36510 echo_area_buffer[0] = echo_area_buffer[1] = Qnil;
36511 staticpro (&echo_area_buffer[0]);
36512 staticpro (&echo_area_buffer[1]);
36513
36514 DEFVAR_LISP ("messages-buffer-name", Vmessages_buffer_name,
36515 doc:
36516
36517
36518
36519 );
36520 Vmessages_buffer_name = build_string ("*Messages*");
36521
36522 mode_line_proptrans_alist = Qnil;
36523 staticpro (&mode_line_proptrans_alist);
36524 mode_line_string_list = Qnil;
36525 staticpro (&mode_line_string_list);
36526 mode_line_string_face = Qnil;
36527 staticpro (&mode_line_string_face);
36528 mode_line_string_face_prop = Qnil;
36529 staticpro (&mode_line_string_face_prop);
36530 Vmode_line_unwind_vector = Qnil;
36531 staticpro (&Vmode_line_unwind_vector);
36532
36533 DEFSYM (Qmode_line_default_help_echo, "mode-line-default-help-echo");
36534
36535 help_echo_string = Qnil;
36536 staticpro (&help_echo_string);
36537 help_echo_object = Qnil;
36538 staticpro (&help_echo_object);
36539 help_echo_window = Qnil;
36540 staticpro (&help_echo_window);
36541 previous_help_echo_string = Qnil;
36542 staticpro (&previous_help_echo_string);
36543 help_echo_pos = -1;
36544
36545 DEFSYM (Qright_to_left, "right-to-left");
36546 DEFSYM (Qleft_to_right, "left-to-right");
36547 defsubr (&Sbidi_resolved_levels);
36548
36549 #ifdef HAVE_WINDOW_SYSTEM
36550 DEFVAR_BOOL ("x-stretch-cursor", x_stretch_cursor_p,
36551 doc:
36552
36553 );
36554 x_stretch_cursor_p = 0;
36555 #endif
36556
36557 DEFVAR_LISP ("show-trailing-whitespace", Vshow_trailing_whitespace,
36558 doc:
36559 );
36560 Vshow_trailing_whitespace = Qnil;
36561
36562 DEFVAR_LISP ("mode-line-compact", Vmode_line_compact,
36563 doc:
36564
36565
36566 );
36567 Vmode_line_compact = Qnil;
36568 DEFSYM (Qlong, "long");
36569
36570 DEFVAR_LISP ("nobreak-char-display", Vnobreak_char_display,
36571 doc:
36572
36573
36574
36575
36576
36577
36578
36579
36580
36581
36582
36583 );
36584 Vnobreak_char_display = Qt;
36585
36586 DEFVAR_BOOL ("nobreak-char-ascii-display", nobreak_char_ascii_display,
36587 doc:
36588
36589
36590
36591
36592
36593
36594
36595
36596
36597
36598
36599
36600
36601
36602
36603 );
36604 nobreak_char_ascii_display = false;
36605
36606 DEFVAR_LISP ("void-text-area-pointer", Vvoid_text_area_pointer,
36607 doc:
36608
36609
36610 );
36611 Vvoid_text_area_pointer = Qarrow;
36612
36613 DEFVAR_LISP ("inhibit-redisplay", Vinhibit_redisplay,
36614 doc:
36615 );
36616 Vinhibit_redisplay = Qnil;
36617
36618 DEFVAR_LISP ("global-mode-string", Vglobal_mode_string,
36619 doc: );
36620 Vglobal_mode_string = Qnil;
36621
36622 DEFVAR_LISP ("overlay-arrow-position", Voverlay_arrow_position,
36623 doc:
36624
36625 );
36626 Voverlay_arrow_position = Qnil;
36627
36628 DEFVAR_LISP ("overlay-arrow-string", Voverlay_arrow_string,
36629 doc:
36630 );
36631 Voverlay_arrow_string = build_pure_c_string ("=>");
36632
36633 DEFVAR_LISP ("overlay-arrow-variable-list", Voverlay_arrow_variable_list,
36634 doc:
36635
36636 );
36637 Voverlay_arrow_variable_list
36638 = list1 (intern_c_string ("overlay-arrow-position"));
36639
36640 DEFVAR_INT ("scroll-step", emacs_scroll_step,
36641 doc:
36642
36643
36644
36645 );
36646
36647 DEFVAR_INT ("scroll-conservatively", scroll_conservatively,
36648 doc:
36649
36650
36651
36652
36653
36654
36655
36656
36657
36658 );
36659 scroll_conservatively = 0;
36660
36661 DEFVAR_INT ("scroll-margin", scroll_margin,
36662 doc:
36663
36664 );
36665 scroll_margin = 0;
36666
36667 DEFVAR_LISP ("maximum-scroll-margin", Vmaximum_scroll_margin,
36668 doc:
36669
36670
36671
36672 );
36673 Vmaximum_scroll_margin = make_float (0.25);
36674
36675 DEFVAR_LISP ("display-pixels-per-inch", Vdisplay_pixels_per_inch,
36676 doc:
36677 );
36678 Vdisplay_pixels_per_inch = make_float (72.0);
36679
36680 #ifdef GLYPH_DEBUG
36681 DEFVAR_INT ("debug-end-pos", debug_end_pos, doc: );
36682 #endif
36683
36684 DEFVAR_LISP ("truncate-partial-width-windows",
36685 Vtruncate_partial_width_windows,
36686 doc:
36687
36688
36689
36690
36691
36692
36693
36694
36695
36696
36697
36698
36699
36700
36701
36702 );
36703 Vtruncate_partial_width_windows = make_fixnum (50);
36704
36705 DEFVAR_BOOL("word-wrap-by-category", word_wrap_by_category, doc:
36706
36707
36708
36709
36710
36711
36712
36713
36714
36715
36716
36717
36718
36719 );
36720 word_wrap_by_category = false;
36721
36722 DEFVAR_LISP ("line-number-display-limit", Vline_number_display_limit,
36723 doc:
36724
36725 );
36726 Vline_number_display_limit = Qnil;
36727
36728 DEFVAR_INT ("line-number-display-limit-width",
36729 line_number_display_limit_width,
36730 doc:
36731
36732 );
36733 line_number_display_limit_width = 200;
36734
36735 DEFVAR_BOOL ("highlight-nonselected-windows", highlight_nonselected_windows,
36736 doc:
36737
36738 );
36739 highlight_nonselected_windows = false;
36740
36741 DEFVAR_BOOL ("multiple-frames", multiple_frames,
36742 doc:
36743
36744
36745 );
36746
36747 DEFVAR_LISP ("frame-title-format", Vframe_title_format,
36748 doc:
36749
36750
36751
36752
36753 );
36754
36755 DEFVAR_LISP ("icon-title-format", Vicon_title_format,
36756 doc:
36757
36758
36759
36760
36761
36762 );
36763
36764
36765 Lisp_Object icon_title_name_format
36766 = pure_list (empty_unibyte_string,
36767 build_pure_c_string ("%b - GNU Emacs at "),
36768 intern_c_string ("system-name"));
36769 Vicon_title_format
36770 = Vframe_title_format
36771 = pure_list (intern_c_string ("multiple-frames"),
36772 build_pure_c_string ("%b"),
36773 icon_title_name_format);
36774
36775 DEFVAR_LISP ("message-log-max", Vmessage_log_max,
36776 doc:
36777
36778 );
36779 Vmessage_log_max = make_fixnum (1000);
36780
36781 DEFVAR_LISP ("window-scroll-functions", Vwindow_scroll_functions,
36782 doc:
36783
36784
36785
36786
36787
36788
36789
36790
36791
36792
36793
36794
36795
36796 );
36797 Vwindow_scroll_functions = Qnil;
36798
36799 DEFVAR_LISP ("mouse-autoselect-window", Vmouse_autoselect_window,
36800 doc:
36801
36802
36803
36804
36805
36806
36807
36808
36809
36810
36811
36812
36813
36814
36815
36816
36817
36818 );
36819 Vmouse_autoselect_window = Qnil;
36820
36821 DEFVAR_LISP ("auto-resize-tab-bars", Vauto_resize_tab_bars,
36822 doc:
36823
36824
36825
36826
36827 );
36828 Vauto_resize_tab_bars = Qt;
36829
36830 DEFVAR_BOOL ("auto-raise-tab-bar-buttons", auto_raise_tab_bar_buttons_p,
36831 doc: );
36832 auto_raise_tab_bar_buttons_p = true;
36833
36834 DEFVAR_LISP ("auto-resize-tool-bars", Vauto_resize_tool_bars,
36835 doc:
36836
36837
36838
36839
36840 );
36841 Vauto_resize_tool_bars = Qt;
36842
36843 DEFVAR_BOOL ("auto-raise-tool-bar-buttons", auto_raise_tool_bar_buttons_p,
36844 doc: );
36845 auto_raise_tool_bar_buttons_p = true;
36846
36847 DEFVAR_LISP ("make-cursor-line-fully-visible", Vmake_cursor_line_fully_visible,
36848 doc:
36849
36850
36851
36852
36853 );
36854 Vmake_cursor_line_fully_visible = Qt;
36855 DEFSYM (Qmake_cursor_line_fully_visible, "make-cursor-line-fully-visible");
36856
36857 DEFVAR_BOOL ("make-window-start-visible", make_window_start_visible,
36858 doc: );
36859 make_window_start_visible = false;
36860 DEFSYM (Qmake_window_start_visible, "make-window-start-visible");
36861 Fmake_variable_buffer_local (Qmake_window_start_visible);
36862
36863 DEFSYM (Qclose_tab, "close-tab");
36864 DEFVAR_LISP ("tab-bar-border", Vtab_bar_border,
36865 doc:
36866
36867
36868
36869 );
36870 Vtab_bar_border = Qinternal_border_width;
36871
36872 DEFVAR_LISP ("tab-bar-button-margin", Vtab_bar_button_margin,
36873 doc:
36874
36875
36876
36877 );
36878 Vtab_bar_button_margin = make_fixnum (DEFAULT_TAB_BAR_BUTTON_MARGIN);
36879
36880 DEFVAR_INT ("tab-bar-button-relief", tab_bar_button_relief,
36881 doc: );
36882 tab_bar_button_relief = DEFAULT_TAB_BAR_BUTTON_RELIEF;
36883
36884 DEFVAR_LISP ("tool-bar-border", Vtool_bar_border,
36885 doc:
36886
36887
36888
36889 );
36890 Vtool_bar_border = Qinternal_border_width;
36891
36892 DEFVAR_LISP ("tool-bar-button-margin", Vtool_bar_button_margin,
36893 doc:
36894
36895
36896
36897 );
36898 Vtool_bar_button_margin = make_fixnum (DEFAULT_TOOL_BAR_BUTTON_MARGIN);
36899
36900 DEFVAR_INT ("tool-bar-button-relief", tool_bar_button_relief,
36901 doc: );
36902 tool_bar_button_relief = DEFAULT_TOOL_BAR_BUTTON_RELIEF;
36903
36904 DEFVAR_LISP ("tool-bar-style", Vtool_bar_style,
36905 doc:
36906
36907
36908
36909
36910
36911
36912
36913
36914 );
36915 Vtool_bar_style = Qnil;
36916
36917 DEFVAR_INT ("tool-bar-max-label-size", tool_bar_max_label_size,
36918 doc:
36919
36920 );
36921 tool_bar_max_label_size = DEFAULT_TOOL_BAR_LABEL_SIZE;
36922
36923 DEFVAR_LISP ("fontification-functions", Vfontification_functions,
36924 doc:
36925
36926
36927
36928
36929
36930
36931
36932
36933 );
36934 Vfontification_functions = Qnil;
36935 Fmake_variable_buffer_local (Qfontification_functions);
36936
36937 DEFVAR_BOOL ("unibyte-display-via-language-environment",
36938 unibyte_display_via_language_environment,
36939 doc:
36940
36941
36942
36943
36944
36945
36946 );
36947 unibyte_display_via_language_environment = false;
36948
36949 DEFVAR_LISP ("max-mini-window-height", Vmax_mini_window_height,
36950 doc:
36951
36952
36953
36954 );
36955 Vmax_mini_window_height = make_float (0.25);
36956
36957 DEFVAR_LISP ("resize-mini-windows", Vresize_mini_windows,
36958 doc:
36959
36960
36961
36962
36963
36964
36965
36966
36967 );
36968
36969
36970
36971
36972
36973 Vresize_mini_windows = Qnil;
36974
36975 DEFVAR_LISP ("blink-cursor-alist", Vblink_cursor_alist,
36976 doc:
36977
36978
36979
36980
36981
36982
36983
36984 );
36985 Vblink_cursor_alist = Qnil;
36986
36987 DEFVAR_LISP ("auto-hscroll-mode", automatic_hscrolling,
36988 doc:
36989
36990
36991
36992 );
36993 automatic_hscrolling = Qt;
36994 DEFSYM (Qauto_hscroll_mode, "auto-hscroll-mode");
36995 DEFSYM (Qcurrent_line, "current-line");
36996
36997 DEFVAR_INT ("hscroll-margin", hscroll_margin,
36998 doc:
36999 );
37000 hscroll_margin = 5;
37001
37002 DEFVAR_LISP ("hscroll-step", Vhscroll_step,
37003 doc:
37004
37005
37006
37007
37008
37009
37010
37011
37012
37013
37014
37015
37016
37017 );
37018 Vhscroll_step = make_fixnum (0);
37019
37020 DEFVAR_BOOL ("message-truncate-lines", message_truncate_lines,
37021 doc:
37022 );
37023 message_truncate_lines = false;
37024
37025 DEFVAR_LISP ("menu-bar-update-hook", Vmenu_bar_update_hook,
37026 doc:
37027
37028
37029 );
37030 Vmenu_bar_update_hook = Qnil;
37031
37032 DEFVAR_LISP ("menu-updating-frame", Vmenu_updating_frame,
37033 doc:
37034 );
37035 Vmenu_updating_frame = Qnil;
37036
37037 DEFVAR_BOOL ("inhibit-menubar-update", inhibit_menubar_update,
37038 doc: );
37039 inhibit_menubar_update = false;
37040
37041 DEFVAR_LISP ("wrap-prefix", Vwrap_prefix,
37042 doc:
37043
37044
37045
37046
37047
37048
37049 );
37050 Vwrap_prefix = Qnil;
37051 DEFSYM (Qwrap_prefix, "wrap-prefix");
37052 Fmake_variable_buffer_local (Qwrap_prefix);
37053
37054 DEFVAR_LISP ("line-prefix", Vline_prefix,
37055 doc:
37056
37057
37058
37059
37060
37061
37062 );
37063 Vline_prefix = Qnil;
37064 DEFSYM (Qline_prefix, "line-prefix");
37065 Fmake_variable_buffer_local (Qline_prefix);
37066
37067 DEFVAR_LISP ("display-line-numbers", Vdisplay_line_numbers,
37068 doc:
37069
37070
37071
37072
37073
37074
37075
37076
37077
37078
37079
37080
37081
37082
37083
37084
37085
37086
37087
37088
37089
37090
37091 );
37092 Vdisplay_line_numbers = Qnil;
37093 DEFSYM (Qdisplay_line_numbers, "display-line-numbers");
37094 Fmake_variable_buffer_local (Qdisplay_line_numbers);
37095 DEFSYM (Qrelative, "relative");
37096 DEFSYM (Qvisual, "visual");
37097
37098 DEFVAR_LISP ("display-line-numbers-width", Vdisplay_line_numbers_width,
37099 doc:
37100
37101
37102
37103 );
37104 Vdisplay_line_numbers_width = Qnil;
37105 DEFSYM (Qdisplay_line_numbers_width, "display-line-numbers-width");
37106 Fmake_variable_buffer_local (Qdisplay_line_numbers_width);
37107
37108 DEFVAR_LISP ("display-line-numbers-current-absolute",
37109 Vdisplay_line_numbers_current_absolute,
37110 doc:
37111
37112 );
37113 Vdisplay_line_numbers_current_absolute = Qt;
37114
37115 DEFVAR_BOOL ("display-line-numbers-widen", display_line_numbers_widen,
37116 doc: );
37117 display_line_numbers_widen = false;
37118 DEFSYM (Qdisplay_line_numbers_widen, "display-line-numbers-widen");
37119 Fmake_variable_buffer_local (Qdisplay_line_numbers_widen);
37120
37121 DEFVAR_INT ("display-line-numbers-offset", display_line_numbers_offset,
37122 doc:
37123
37124
37125 );
37126 display_line_numbers_offset = 0;
37127 DEFSYM (Qdisplay_line_numbers_offset, "display-line-numbers-offset");
37128 Fmake_variable_buffer_local (Qdisplay_line_numbers_offset);
37129
37130 DEFVAR_BOOL ("display-fill-column-indicator", display_fill_column_indicator,
37131 doc:
37132
37133
37134 );
37135 display_fill_column_indicator = false;
37136 DEFSYM (Qdisplay_fill_column_indicator, "display-fill-column-indicator");
37137 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator);
37138
37139 DEFVAR_LISP ("display-fill-column-indicator-column", Vdisplay_fill_column_indicator_column,
37140 doc:
37141
37142
37143
37144 );
37145 Vdisplay_fill_column_indicator_column = Qt;
37146 DEFSYM (Qdisplay_fill_column_indicator_column, "display-fill-column-indicator-column");
37147 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_column);
37148
37149 DEFVAR_LISP ("display-fill-column-indicator-character", Vdisplay_fill_column_indicator_character,
37150 doc:
37151
37152
37153 );
37154 Vdisplay_fill_column_indicator_character = Qnil;
37155 DEFSYM (Qdisplay_fill_column_indicator_character, "display-fill-column-indicator-character");
37156 Fmake_variable_buffer_local (Qdisplay_fill_column_indicator_character);
37157
37158 DEFVAR_INT ("display-line-numbers-major-tick", display_line_numbers_major_tick,
37159 doc:
37160
37161
37162 );
37163 display_line_numbers_major_tick = 0;
37164
37165 DEFVAR_INT ("display-line-numbers-minor-tick", display_line_numbers_minor_tick,
37166 doc:
37167
37168
37169 );
37170 display_line_numbers_minor_tick = 0;
37171
37172 DEFVAR_BOOL ("inhibit-eval-during-redisplay", inhibit_eval_during_redisplay,
37173 doc: );
37174 inhibit_eval_during_redisplay = false;
37175
37176 DEFVAR_BOOL ("inhibit-free-realized-faces", inhibit_free_realized_faces,
37177 doc: );
37178 inhibit_free_realized_faces = false;
37179
37180 DEFVAR_BOOL ("inhibit-bidi-mirroring", inhibit_bidi_mirroring,
37181 doc:
37182
37183 );
37184 inhibit_bidi_mirroring = false;
37185
37186 DEFVAR_BOOL ("bidi-inhibit-bpa", bidi_inhibit_bpa,
37187 doc:
37188
37189
37190
37191 );
37192 bidi_inhibit_bpa = false;
37193
37194 #ifdef GLYPH_DEBUG
37195 DEFVAR_BOOL ("inhibit-try-window-id", inhibit_try_window_id,
37196 doc: );
37197 inhibit_try_window_id = false;
37198
37199 DEFVAR_BOOL ("inhibit-try-window-reusing", inhibit_try_window_reusing,
37200 doc: );
37201 inhibit_try_window_reusing = false;
37202
37203 DEFVAR_BOOL ("inhibit-try-cursor-movement", inhibit_try_cursor_movement,
37204 doc: );
37205 inhibit_try_cursor_movement = false;
37206 #endif
37207
37208 DEFVAR_INT ("overline-margin", overline_margin,
37209 doc:
37210
37211 );
37212 overline_margin = 2;
37213
37214 DEFVAR_INT ("underline-minimum-offset",
37215 underline_minimum_offset,
37216 doc:
37217
37218
37219
37220 );
37221 underline_minimum_offset = 1;
37222 DEFSYM (Qunderline_minimum_offset, "underline-minimum-offset");
37223
37224 DEFVAR_BOOL ("display-hourglass", display_hourglass_p,
37225 doc:
37226
37227 );
37228 display_hourglass_p = true;
37229
37230 DEFVAR_LISP ("hourglass-delay", Vhourglass_delay,
37231 doc: );
37232 Vhourglass_delay = make_fixnum (DEFAULT_HOURGLASS_DELAY);
37233
37234 #ifdef HAVE_WINDOW_SYSTEM
37235 hourglass_atimer = NULL;
37236 hourglass_shown_p = false;
37237 #endif
37238
37239
37240 DEFSYM (Qglyphless_char, "glyphless-char");
37241
37242
37243 DEFSYM (Qhex_code, "hex-code");
37244 DEFSYM (Qempty_box, "empty-box");
37245 DEFSYM (Qthin_space, "thin-space");
37246 DEFSYM (Qzero_width, "zero-width");
37247
37248 DEFVAR_LISP ("pre-redisplay-function", Vpre_redisplay_function,
37249 doc:
37250
37251
37252 );
37253 Vpre_redisplay_function = intern ("ignore");
37254
37255
37256 DEFSYM (Qglyphless_char_display, "glyphless-char-display");
37257 Fput (Qglyphless_char_display, Qchar_table_extra_slots, make_fixnum (1));
37258
37259 DEFVAR_LISP ("glyphless-char-display", Vglyphless_char_display,
37260 doc:
37261
37262
37263
37264
37265
37266
37267
37268
37269
37270
37271
37272
37273
37274
37275
37276
37277
37278
37279
37280
37281
37282
37283
37284 );
37285 Vglyphless_char_display = Fmake_char_table (Qglyphless_char_display, Qnil);
37286 Fset_char_table_extra_slot (Vglyphless_char_display, make_fixnum (0),
37287 Qempty_box);
37288
37289 DEFVAR_LISP ("debug-on-message", Vdebug_on_message,
37290 doc: );
37291 Vdebug_on_message = Qnil;
37292
37293 DEFVAR_LISP ("set-message-function", Vset_message_function,
37294 doc:
37295
37296
37297
37298
37299
37300
37301
37302
37303
37304 );
37305 Vset_message_function = Qnil;
37306
37307 DEFSYM (Qdont_clear_message, "dont-clear-message");
37308 DEFVAR_LISP ("clear-message-function", Vclear_message_function,
37309 doc:
37310
37311
37312
37313
37314
37315
37316
37317
37318
37319
37320 );
37321 Vclear_message_function = Qnil;
37322
37323 DEFVAR_LISP ("redisplay--all-windows-cause", Vredisplay__all_windows_cause,
37324 doc:
37325 );
37326 Vredisplay__all_windows_cause = Fmake_hash_table (0, NULL);
37327
37328 DEFVAR_LISP ("redisplay--mode-lines-cause", Vredisplay__mode_lines_cause,
37329 doc:
37330 );
37331 Vredisplay__mode_lines_cause = Fmake_hash_table (0, NULL);
37332
37333 DEFVAR_BOOL ("redisplay--inhibit-bidi", redisplay__inhibit_bidi,
37334 doc: );
37335
37336
37337 redisplay__inhibit_bidi = true;
37338
37339 DEFVAR_BOOL ("display-raw-bytes-as-hex", display_raw_bytes_as_hex,
37340 doc:
37341
37342 );
37343 display_raw_bytes_as_hex = false;
37344
37345 DEFVAR_BOOL ("mouse-fine-grained-tracking", mouse_fine_grained_tracking,
37346 doc:
37347
37348 );
37349 mouse_fine_grained_tracking = false;
37350
37351 DEFVAR_BOOL ("tab-bar--dragging-in-progress", tab_bar__dragging_in_progress,
37352 doc: );
37353 tab_bar__dragging_in_progress = false;
37354
37355 DEFVAR_BOOL ("redisplay-skip-initial-frame", redisplay_skip_initial_frame,
37356 doc:
37357
37358
37359
37360 );
37361 redisplay_skip_initial_frame = true;
37362
37363 DEFVAR_BOOL ("redisplay-skip-fontification-on-input",
37364 redisplay_skip_fontification_on_input,
37365 doc:
37366
37367
37368
37369
37370
37371
37372
37373 );
37374 redisplay_skip_fontification_on_input = false;
37375
37376 DEFVAR_BOOL ("redisplay-adhoc-scroll-in-resize-mini-windows",
37377 redisplay_adhoc_scroll_in_resize_mini_windows,
37378 doc:
37379
37380 );
37381
37382 redisplay_adhoc_scroll_in_resize_mini_windows = true;
37383
37384 DEFVAR_BOOL ("composition-break-at-point", composition_break_at_point,
37385 doc:
37386
37387 );
37388 composition_break_at_point = false;
37389
37390 DEFVAR_INT ("max-redisplay-ticks", max_redisplay_ticks,
37391 doc:
37392
37393
37394
37395
37396
37397
37398
37399
37400
37401
37402
37403 );
37404 max_redisplay_ticks = 0;
37405 }
37406
37407
37408
37409
37410 void
37411 init_xdisp (void)
37412 {
37413 CHARPOS (this_line_start_pos) = 0;
37414
37415 echo_area_window = minibuf_window;
37416
37417 if (!noninteractive)
37418 {
37419 struct window *m = XWINDOW (minibuf_window);
37420 Lisp_Object frame = m->frame;
37421 struct frame *f = XFRAME (frame);
37422 Lisp_Object root = FRAME_ROOT_WINDOW (f);
37423 struct window *r = XWINDOW (root);
37424 int i;
37425
37426 r->top_line = FRAME_TOP_MARGIN (f);
37427 r->pixel_top = r->top_line * FRAME_LINE_HEIGHT (f);
37428 r->total_cols = FRAME_COLS (f);
37429 r->pixel_width = r->total_cols * FRAME_COLUMN_WIDTH (f);
37430 r->total_lines = FRAME_TOTAL_LINES (f) - 1 - FRAME_TOP_MARGIN (f);
37431 r->pixel_height = r->total_lines * FRAME_LINE_HEIGHT (f);
37432
37433 m->top_line = FRAME_TOTAL_LINES (f) - 1;
37434 m->pixel_top = m->top_line * FRAME_LINE_HEIGHT (f);
37435 m->total_cols = FRAME_COLS (f);
37436 m->pixel_width = m->total_cols * FRAME_COLUMN_WIDTH (f);
37437 m->total_lines = 1;
37438 m->pixel_height = m->total_lines * FRAME_LINE_HEIGHT (f);
37439
37440 scratch_glyph_row.glyphs[TEXT_AREA] = scratch_glyphs;
37441 scratch_glyph_row.glyphs[TEXT_AREA + 1]
37442 = scratch_glyphs + MAX_SCRATCH_GLYPHS;
37443
37444
37445 for (i = 0; i < 3; ++i)
37446 default_invis_vector[i] = make_fixnum ('.');
37447 }
37448
37449 {
37450
37451
37452 int size = 100;
37453 mode_line_noprop_buf = xmalloc (size);
37454 mode_line_noprop_buf_end = mode_line_noprop_buf + size;
37455 mode_line_noprop_ptr = mode_line_noprop_buf;
37456 mode_line_target = MODE_LINE_DISPLAY;
37457 }
37458
37459 help_echo_showing_p = false;
37460 }
37461
37462 #ifdef HAVE_WINDOW_SYSTEM
37463
37464
37465
37466
37467
37468 static void
37469 show_hourglass (struct atimer *timer)
37470 {
37471
37472
37473
37474 hourglass_atimer = NULL;
37475
37476 if (!hourglass_shown_p)
37477 {
37478 Lisp_Object tail, frame;
37479
37480 block_input ();
37481
37482 FOR_EACH_FRAME (tail, frame)
37483 {
37484 struct frame *f = XFRAME (frame);
37485
37486 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37487 && FRAME_RIF (f)->show_hourglass)
37488 FRAME_RIF (f)->show_hourglass (f);
37489 }
37490
37491 hourglass_shown_p = true;
37492 unblock_input ();
37493 }
37494 }
37495
37496
37497
37498 void
37499 start_hourglass (void)
37500 {
37501 struct timespec delay;
37502
37503 cancel_hourglass ();
37504
37505 if (FIXNUMP (Vhourglass_delay)
37506 && XFIXNUM (Vhourglass_delay) > 0)
37507 delay = make_timespec (min (XFIXNUM (Vhourglass_delay),
37508 TYPE_MAXIMUM (time_t)),
37509 0);
37510 else if (FLOATP (Vhourglass_delay)
37511 && XFLOAT_DATA (Vhourglass_delay) > 0)
37512 delay = dtotimespec (XFLOAT_DATA (Vhourglass_delay));
37513 else
37514 delay = make_timespec (DEFAULT_HOURGLASS_DELAY, 0);
37515
37516 hourglass_atimer = start_atimer (ATIMER_RELATIVE, delay,
37517 show_hourglass, NULL);
37518 }
37519
37520
37521
37522
37523 void
37524 cancel_hourglass (void)
37525 {
37526 if (hourglass_atimer)
37527 {
37528 cancel_atimer (hourglass_atimer);
37529 hourglass_atimer = NULL;
37530 }
37531
37532 if (hourglass_shown_p)
37533 {
37534 Lisp_Object tail, frame;
37535
37536 block_input ();
37537
37538 FOR_EACH_FRAME (tail, frame)
37539 {
37540 struct frame *f = XFRAME (frame);
37541
37542 if (FRAME_LIVE_P (f) && FRAME_WINDOW_P (f)
37543 && FRAME_RIF (f)->hide_hourglass)
37544 FRAME_RIF (f)->hide_hourglass (f);
37545 #ifdef HAVE_NTGUI
37546
37547 else if (!FRAME_W32_P (f))
37548 w32_arrow_cursor ();
37549 #endif
37550 }
37551
37552 hourglass_shown_p = false;
37553 unblock_input ();
37554 }
37555 }
37556
37557
37558
37559
37560
37561
37562
37563
37564 static int
37565 adjust_glyph_width_for_mouse_face (struct glyph *g, struct glyph_row *row,
37566 struct window *w,
37567 struct face *original_face,
37568 struct face *mouse_face)
37569 {
37570 int sum = 0;
37571
37572 bool do_left_box_p = g->left_box_line_p;
37573 bool do_right_box_p = g->right_box_line_p;
37574
37575
37576
37577 if (g->type == IMAGE_GLYPH)
37578 {
37579 if (!row->reversed_p)
37580 {
37581 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37582 g->u.img_id);
37583 do_left_box_p = g->left_box_line_p &&
37584 g->slice.img.x == 0;
37585 do_right_box_p = g->right_box_line_p &&
37586 g->slice.img.x + g->slice.img.width == img->width;
37587 }
37588 else
37589 {
37590 struct image *img = IMAGE_FROM_ID (WINDOW_XFRAME (w),
37591 g->u.img_id);
37592 do_left_box_p = g->left_box_line_p &&
37593 g->slice.img.x + g->slice.img.width == img->width;
37594 do_right_box_p = g->right_box_line_p &&
37595 g->slice.img.x == 0;
37596 }
37597 }
37598
37599
37600 if (do_left_box_p)
37601 sum -= max (0, original_face->box_vertical_line_width);
37602
37603
37604 if (do_right_box_p)
37605 sum -= max (0, original_face->box_vertical_line_width);
37606
37607 if (g->left_box_line_p)
37608 sum += max (0, mouse_face->box_vertical_line_width);
37609 if (g->right_box_line_p)
37610 sum += max (0, mouse_face->box_vertical_line_width);
37611
37612 return sum;
37613 }
37614
37615
37616
37617
37618
37619
37620
37621
37622
37623 static void
37624 get_cursor_offset_for_mouse_face (struct window *w, struct glyph_row *row,
37625 int *offset)
37626 {
37627 int sum = 0;
37628
37629 if (row->mode_line_p)
37630 return;
37631
37632 block_input ();
37633
37634 struct frame *f = WINDOW_XFRAME (w);
37635 Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
37636 struct glyph *start, *end;
37637 struct face *mouse_face = FACE_FROM_ID (f, hlinfo->mouse_face_face_id);
37638 int hpos = w->phys_cursor.hpos;
37639 end = &row->glyphs[TEXT_AREA][hpos];
37640
37641 if (!row->reversed_p)
37642 {
37643 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37644 hlinfo->mouse_face_beg_row)
37645 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_beg_col];
37646 else
37647 start = row->glyphs[TEXT_AREA];
37648 }
37649 else
37650 {
37651 if (MATRIX_ROW_VPOS (row, w->current_matrix) ==
37652 hlinfo->mouse_face_end_row)
37653 start = &row->glyphs[TEXT_AREA][hlinfo->mouse_face_end_col];
37654 else
37655 start = &row->glyphs[TEXT_AREA][row->used[TEXT_AREA] - 1];
37656 }
37657
37658
37659
37660
37661 for ( ; row->reversed_p ? start > end : start < end;
37662 row->reversed_p ? --start : ++start)
37663 sum += adjust_glyph_width_for_mouse_face (start, row, w,
37664 FACE_FROM_ID (f, start->face_id),
37665 mouse_face);
37666
37667 if (row->reversed_p)
37668 sum = -sum;
37669
37670 *offset = sum;
37671
37672 unblock_input ();
37673 }
37674 #endif